Pull commits from upstream for java 11 compatibility!

(cherry picked from commit 1410e008c8ea196afec98d7766e6dca5c9d555b4)

Test: make javaparser, with the default OpenJDK 9 toolchain and an OpenJDK 11 toolchain
Bug: 135178920
Merged-In: I27826ba60af5c54848e2eae40930d8fb8a302919
Change-Id: Iecc272dbce30747131f2c2ae03fdb39965bc838b
diff --git a/.gitignore b/.gitignore
index 16db129..8d37cb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,39 +6,22 @@
 *~
 .project
 .classpath
+.idea/
+*.iml
 release.properties
 **/.DS_Store
 
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
 # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
 hs_err_pid*
 
 .gradle
+*.ipr
+*.iws
 build-*
 *.asc
 build
 out
 .java-version
-
-
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff:
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/dictionaries
-
-# Sensitive or high-churn files:
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.xml
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-
-# Gradle:
-.idea/**/gradle.xml
-.idea/**/libraries
-
-*.iws
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index eac2ad1..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-javaparser-parent
\ No newline at end of file
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
deleted file mode 100644
index d7c1d0e..0000000
--- a/.idea/codeStyleSettings.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectCodeStyleSettingsManager">
-    <option name="PER_PROJECT_SETTINGS">
-      <value />
-    </option>
-    <option name="PREFERRED_PROJECT_CODE_STYLE" value="JavaParser" />
-  </component>
-</project>
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
deleted file mode 100644
index 0aebde2..0000000
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<component name="ProjectCodeStyleConfiguration">
-  <state>
-    <option name="PREFERRED_PROJECT_CODE_STYLE" value="JavaParser" />
-  </state>
-</component>
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index a785d8b..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="CompilerConfiguration">
-    <annotationProcessing>
-      <profile name="Maven default annotation processors profile" enabled="true">
-        <sourceOutputDir name="target/generated-sources/annotations" />
-        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
-        <outputRelativeToContentRoot value="true" />
-        <module name="javaparser-core" />
-        <module name="javaparser-core-generators" />
-        <module name="javaparser-metamodel-generator" />
-        <module name="javaparser-symbol-solver-core" />
-        <module name="javaparser-symbol-solver-logic" />
-        <module name="javaparser-symbol-solver-model" />
-        <module name="javaparser-symbol-solver-testing" />
-        <module name="javaparser-testing" />
-      </profile>
-    </annotationProcessing>
-    <bytecodeTargetLevel>
-      <module name="javaparser-core" target="1.8" />
-      <module name="javaparser-core-generators" target="1.8" />
-      <module name="javaparser-metamodel-generator" target="1.8" />
-      <module name="javaparser-parent" target="1.8" />
-      <module name="javaparser-symbol-solver-core" target="1.8" />
-      <module name="javaparser-symbol-solver-logic" target="1.8" />
-      <module name="javaparser-symbol-solver-model" target="1.8" />
-      <module name="javaparser-symbol-solver-testing" target="1.8" />
-      <module name="javaparser-testing" target="1.8" />
-    </bytecodeTargetLevel>
-  </component>
-</project>
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index 4d6b457..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="Encoding">
-    <file url="file://$PROJECT_DIR$" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-core" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-core-generators" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-metamodel-generator" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-symbol-solver-core" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-symbol-solver-logic" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-symbol-solver-model" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-symbol-solver-testing" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/javaparser-testing" charset="UTF-8" />
-  </component>
-</project>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 146ab09..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<component name="InspectionProjectProfileManager">
-  <profile version="1.0">
-    <option name="myName" value="Project Default" />
-    <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
-      <option name="processCode" value="true" />
-      <option name="processLiterals" value="true" />
-      <option name="processComments" value="true" />
-    </inspection_tool>
-  </profile>
-</component>
\ No newline at end of file
diff --git a/.idea/markdown-doclet.xml b/.idea/markdown-doclet.xml
deleted file mode 100644
index d7bd314..0000000
--- a/.idea/markdown-doclet.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ch.raffael.mddoclet.integrations.idea.MarkdownDocletIdea.ProjectConfiguration">
-    <option name="enabled" value="true" />
-    <option name="renderingOptions">
-      <RenderingOptions />
-    </option>
-  </component>
-</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 68010fc..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="EntryPointsManager">
-    <list size="4">
-      <item index="0" class="java.lang.String" itemvalue="com.github.javaparser.metamodel.DerivedProperty" />
-      <item index="1" class="java.lang.String" itemvalue="org.jbehave.core.annotations.Given" />
-      <item index="2" class="java.lang.String" itemvalue="org.jbehave.core.annotations.Then" />
-      <item index="3" class="java.lang.String" itemvalue="org.jbehave.core.annotations.When" />
-    </list>
-  </component>
-  <component name="MavenProjectsManager">
-    <option name="originalFiles">
-      <list>
-        <option value="$PROJECT_DIR$/pom.xml" />
-      </list>
-    </option>
-  </component>
-  <component name="ProjectRootManager" version="2" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
-</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 1a08e14..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectModuleManager">
-    <modules>
-      <module fileurl="file://$PROJECT_DIR$/javaparser-core/javaparser-core.iml" filepath="$PROJECT_DIR$/javaparser-core/javaparser-core.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-core-generators/javaparser-core-generators.iml" filepath="$PROJECT_DIR$/javaparser-core-generators/javaparser-core-generators.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-metamodel-generator/javaparser-metamodel-generator.iml" filepath="$PROJECT_DIR$/javaparser-metamodel-generator/javaparser-metamodel-generator.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-parent.iml" filepath="$PROJECT_DIR$/javaparser-parent.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-symbol-solver-core/javaparser-symbol-solver-core.iml" filepath="$PROJECT_DIR$/javaparser-symbol-solver-core/javaparser-symbol-solver-core.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-symbol-solver-logic/javaparser-symbol-solver-logic.iml" filepath="$PROJECT_DIR$/javaparser-symbol-solver-logic/javaparser-symbol-solver-logic.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-symbol-solver-model/javaparser-symbol-solver-model.iml" filepath="$PROJECT_DIR$/javaparser-symbol-solver-model/javaparser-symbol-solver-model.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-symbol-solver-testing/javaparser-symbol-solver-testing.iml" filepath="$PROJECT_DIR$/javaparser-symbol-solver-testing/javaparser-symbol-solver-testing.iml" />
-      <module fileurl="file://$PROJECT_DIR$/javaparser-testing/javaparser-testing.iml" filepath="$PROJECT_DIR$/javaparser-testing/javaparser-testing.iml" />
-    </modules>
-  </component>
-</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="VcsDirectoryMappings">
-    <mapping directory="$PROJECT_DIR$" vcs="Git" />
-  </component>
-</project>
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 640d3ae..03982c9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,12 @@
 sudo: false
 language: java
-install: mvn install -DskipTests=true
-script: mvn test
+install: mvn -B install -DskipTests=true
+script: mvn -B test -P AlsoSlowTests
+cache:
+  directories:
+    - $HOME/.ivy2
 jdk:
-  - oraclejdk8
-  - oraclejdk9
+  - openjdk11
 notifications:
   webhooks:
     urls:
@@ -12,5 +14,11 @@
     on_success: always  # options: [always|never|change] default: always
     on_failure: always  # options: [always|never|change] default: always
 after_success:
-  - mvn test jacoco:report coveralls:report
+  - mvn -B test jacoco:report coveralls:report
 # http://lint.travis-ci.org/ validator
+env:
+  global:
+    - secure: ORUzol/BaGhDxYAH2bd4X+pHVT0/R9CugN3n7mY14CjD1EVBcQahUYtmSg9DlXNUUAb7zrCDPB7vsDXkU8eTttAt/GD74C3mNmG9VUvwWeTIaY2JOcwLmcJkP7cOm3O6c+E2AMa8hXtOUuHkXd0da/vIl+FA4i64IgONdk4AZE8=
+
+after_script:
+  - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./fixup.sh fi
diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..1548fdd
--- /dev/null
+++ b/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1 @@
+Fixes #9999.
diff --git a/appveyor.yml b/appveyor.yml
index f881bfc..de0bdb6 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,5 +1,7 @@
 version: '{build}'
 os: Windows Server 2012
+environment:
+  appveyor_build_worker_cloud: gce
 install:
   - ps: |
       Add-Type -AssemblyName System.IO.Compression.FileSystem
@@ -11,13 +13,14 @@
         [System.IO.Compression.ZipFile]::ExtractToDirectory("C:\maven-bin.zip", "C:\maven")
       }
   - cmd: SET PATH=C:\maven\apache-maven-3.2.5\bin;%JAVA_HOME%\bin;%PATH%
-  - cmd: SET MAVEN_OPTS=-XX:MaxPermSize=2g -Xmx4g
-  - cmd: SET JAVA_OPTS=-XX:MaxPermSize=2g -Xmx4g
+  - cmd: SET MAVEN_OPTS=-Xmx1g
+  - cmd: SET JAVA_OPTS=-Xmx1g
   - cmd: SET M2_HOME=C:\maven\apache-maven-3.2.5
+  - cmd: SET JAVA_HOME=C:\Program Files\Java\jdk10
 build_script:
-  - mvn clean package --batch-mode -DskipTest
+  - echo ignore this
 test_script:
-  - mvn clean install --batch-mode
+  - mvn -B clean install --batch-mode
 cache:
   - C:\maven\
-  - C:\Users\appveyor\.m2
\ No newline at end of file
+  - C:\Users\appveyor\.m2
diff --git a/changelog.md b/changelog.md
index 192f146..5bbe9b2 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,345 @@
+Version 3.14.9
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/145?closed=1)
+
+Version 3.14.8
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/144?closed=1)
+
+Version 3.14.7
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/143?closed=1)
+
+Version 3.14.6 (oops, failed)
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/142?closed=1)
+
+Version 3.14.5
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/141?closed=1)
+
+Version 3.14.4
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/140?closed=1)
+
+Version 3.14.3
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/139?closed=1)
+
+Version 3.14.2
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/138?closed=1)
+
+Version 3.14.1
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/137?closed=1)
+
+Version 3.14.0
+------------------
+* BREAKING: `SuperExpr` and `ThisExpr` used to have an `Expression classExpr`.
+this has been tightened to `Name typeName` which is more specific and easier to use.
+Checking if the expression is a `FieldAccessExpr` or `NameExpr` is no longer needed. 
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/136?closed=1)
+
+Version 3.13.10
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/135?closed=1)
+
+Version 3.13.9
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/134?closed=1)
+
+Version 3.13.8 (failed)
+------------------
+(release failed)
+
+Version 3.13.7
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/133?closed=1)
+
+Version 3.13.6
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/132?closed=1)
+
+Version 3.13.5
+------------------
+* "BREAKING": `ReferenceType.getDirectAncestors()` no longer returns `java.lang.Object` when called on a `ReferenceType` of `java.lang.Object`.
+This remedies infinite recursions in certain edge cases. If you relied on the old behavior, you have to add a `ReferenceType` instance of `java.lang.Object`
+to the List returned by `ReferenceType.getDirectAncestors()` yourself.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/131?closed=1)
+
+Version 3.13.4
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/130?closed=1)
+
+Version 3.13.3
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/129?closed=1)
+
+Version 3.13.2
+------------------
+* Version 3.13.0 and 3.13.1 contain rather bad bugs that have been fixed here.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/128?closed=1)
+
+Version 3.13.1 (buggy!)
+------------------
+* Slightly breaking: most parameters to Log methods now take consumers to avoid evaluating them when not necessary. 
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/127?closed=1)
+
+Version 3.13.0 (buggy!)
+------------------
+* "BREAKING": The static `JavaParser.parse...` methods have moved to `StaticJavaParser.parse...`!
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/126?closed=1)
+
+Version 3.12.0
+------------------
+* "BREAKING": all deprecated code was removed.
+If you don't know what to do, try version 3.11.0 and read the Javadoc for the deprecated methods.
+It tells you what to use instead.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/124?closed=1)
+
+Version 3.11.0
+------------------
+* BREAKING: `SwitchEntryStmt` is now `SwitchEntry`, because it was never a statement.
+* BREAKING: a case in a switch can now have multiple labels,
+so `SwitchEntry` no longer has an `Expression label`,
+but a `NodeList<Expression> label`.
+* This completes *parsing* support for Java 12.
+Symbol resolution is still to be done.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/123?closed=1)
+
+Version 3.10.2
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/122?closed=1)
+
+Version 3.10.1
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/121?closed=1)
+
+Version 3.10.0
+------------------
+* slightly breaking: besides `break;` and `break [label];` there is now `break [expression];` like
+`break 1+2;` or `break "bye!";` . That means that `BreakStmt` no longer has a `label`,
+it has a `value` which is of type `Expression`.
+This is to prepare for Java 12 switch expressions.
+You can find the details in the Javadoc.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/120?closed=1)
+
+Version 3.9.1
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/119?closed=1)
+
+Version 3.9.0
+------------------
+* MAJOR BREAKAGE: modifiers (like public, static, transient) used to be a special case:
+they were enums stored in an EnumSet.
+This meant they were not true `Node`s, had to be treated in a special way, and missed some information.
+This has now been corrected in [PR 1975](https://github.com/javaparser/javaparser/pull/1975). 
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/118?closed=1)
+
+Version 3.8.3
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/117?closed=1)
+
+Version 3.8.2
+------------------
+* slightly breaking: `ObjectCreationExpr` no longer gets a diamond when constructed with the default constructor.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/116?closed=1)
+
+Version 3.8.1
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/114?closed=1)
+
+Version 3.8.0
+------------------
+* A Unicode preprocessing filter is now available again.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/113?closed=1)
+
+Version 3.7.1
+------------------
+* slightly breaking: the enum constants in JsonToken are now capitalized.
+* slightly breaking: [some obscure methods in the symbol solver changed](https://github.com/javaparser/javaparser/pull/1922) 
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/115?closed=1)
+
+Version 3.7.0
+------------------
+* BREAKING: `ForeachStmt` is now correctly capitalized: `ForEachStmt`
+* BREAKING: when using modules, everything that was called `...Statement` is now correctly called `...Directive`
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/112?closed=1)
+
+Version 3.6.27
+------------------
+* The Json serialization now serializes more fields,
+which *should* not impact existing code.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/111?closed=1)
+
+Version 3.6.26
+------------------
+* BREAKING: Node.getData now throws an exception if the data was not set before.
+This can be rewritten by checking with Node.containsData before doing getData.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/110?closed=1)
+
+Version 3.6.25
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/109?closed=1)
+
+Version 3.6.24
+------------------
+* `findAncestor(type, predicate)` is now available
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/108?closed=1)
+
+Version 3.6.23
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/107?closed=1)
+
+Version 3.6.22
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/106?closed=1)
+
+Version 3.6.21
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/105?closed=1)
+
+Version 3.6.20
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/104?closed=1)
+
+Version 3.6.19
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/103?closed=1)
+
+Version 3.6.18
+------------------
+* Parsing Java 11 is now supported.
+* Running on Java 11 is now supported.
+* Building on JDK 11 is NOT yet supported.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/101?closed=1)
+
+Version 3.6.17
+------------------
+* A new artifact was added: javaparser-core-serialization.
+It contains a JSON serializer, and might get more serializers in the future.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/100?closed=1)
+
+Version 3.6.16
+------------------
+* BREAKING: some parts of the module syntax used `Type` where they should have used `Name`.
+This is now fixed, but your code may need to be adapted if you are parsing modules.
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/99?closed=1)
+
+Version 3.6.15
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/98?closed=1)
+
+Version 3.6.14
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/97?closed=1)
+
+Version 3.6.13
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/96?closed=1)
+* JavaParserFacade.getType now can also handle NameExpr referring to types 
+while before they were not supported.
+See [issue #1491](https://github.com/javaparser/javaparser/issues/1491#issuecomment-403277963)
+
+Version 3.6.12
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/95?closed=1)
+
+Version 3.6.10 & Version 3.6.11
+------------------
+* A mixup during the release put all the issues in the same milestone:
+
+[issues resolved](https://github.com/javaparser/javaparser/milestone/94?closed=1)
+
+Version 3.6.9
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/93?closed=1)
+
+Version 3.6.8
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/92?closed=1)
+* Intellij Idea project files were deleted from the repository,
+so if you have a clone of the JP source, your local files will be deleted as well.
+Save anything you want to keep.
+
+Version 3.6.7
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/91?closed=1)
+
+Version 3.6.6
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/90?closed=1)
+* You can now configure the parser inside JavaParserTypeSolver.
+
+Version 3.6.5
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/89?closed=1)
+* Be aware of annotations or indents looking slightly different when output!
+
+Version 3.6.4
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/88?closed=1)
+
+Version 3.6.3
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/87?closed=1)
+
+Version 3.6.2
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/86?closed=1)
+
+Version 3.6.1
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/85?closed=1)
+* BREAKING: `SymbolSolverQuickSetup` has been removed in favor of `ProjectRoot` and `SymbolSolverCollectionStrategy`.
+
+Version 3.6.0
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/84?closed=1)
+* @daanschipper added `ProjectRoot` which is used for analysing and storing project structure.
+* Upgraded version from 3.5.20 to 3.6.0 because people got tired of seeing 3.5.
+
+Version 3.5.20
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/83?closed=1)
+* Thanks to @daanschipper for the PR :-)
+
+Version 3.5.19
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/82?closed=1)
+
+Version 3.5.18
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/81?closed=1)
+
+Version 3.5.17
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/80?closed=1)
+
+Version 3.5.16
+------------------
+[issues resolved](https://github.com/javaparser/javaparser/milestone/79?closed=1)
+
 Version 3.5.15
 ------------------
 [issues resolved](https://github.com/javaparser/javaparser/milestone/78?closed=1)
@@ -287,7 +629,7 @@
 ```
 and like this for the static parse methods:
 ```java
-JavaParser.getStaticConfiguration().setValidator(new Java9Validator());
+QuickJavaParser.getConfiguration().setValidator(new Java9Validator());
 ```
 
 * 862 552 "_" is an illegal identifier on source level 9.
diff --git a/doc/component_diagram.puml b/doc/component_diagram.puml
new file mode 100644
index 0000000..2a219aa
--- /dev/null
+++ b/doc/component_diagram.puml
@@ -0,0 +1,29 @@
+@startuml
+node core {
+    [Java parser] <-- [AST]
+    [Javadoc parser]
+    [AST] <-- [lexical preserving printer]
+    [AST] <-- [concrete syntax model]
+    [concrete syntax model] <-- [lexical preserving printer]
+    events <-- [lexical preserving printer]
+    [AST] <-- [comments inserter]
+    [AST] <-- [visitors]
+    [AST] <-- [meta model]
+    [AST] <-- [pretty printer]
+    [visitors] <-- [pretty printer]
+    [AST] - symbol_resolution
+    [AST] - events
+    [visitors] <-- [code generators]
+    [AST] <-- [code generators]
+    [meta model] <-- [code generators]
+    [AST] <-- [JSON (de)serializer]
+    [Java parser] <- [source root]
+}
+node symbol-solver {
+    [AST] <- [model]
+    symbol_resolution <- [model]
+    [model] <-- [core]
+    [model] <-- [logic]
+    [logic] <-- [core]
+}
+@enduml
\ No newline at end of file
diff --git a/fixup.sh b/fixup.sh
new file mode 100755
index 0000000..c7220d6
--- /dev/null
+++ b/fixup.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+
+mvn org.walkmod.maven.plugins:walkmod-maven-plugin:apply -Dchains=pmd -Dproperties="configurationFile=ruleset.xml" -Dpath=src/main/java
+git diff > walkmod.patch
+
+if [ "$TRAVIS_PULL_REQUEST" = false ] ; then
+    echo 'Skipped build. This is not a pull request'
+    exit 0
+fi
+
+if [ -z "$TRAVIS_REPO_SLUG" ]
+then
+  echo "There is not TRAVIS_REPO_SLUG defined"
+  exit 1
+fi
+
+if [ -z "$TRAVIS_PULL_REQUEST_SHA" ]
+then
+  echo "There is not TRAVIS_PULL_REQUEST_SHA defined"
+  exit 1
+fi
+
+if [ -z "$OCTOPATCH_API_TOKEN" ] ; then
+    echo "There is not OCTOPATCH_API_TOKEN defined"
+    exit 1
+fi
+
+REQUEST="curl -X POST -H \"Content-Type: multipart/form-data\""
+FILES=$(find . -type f -name "*.patch")
+if [ -z "$FILES" ]
+then
+    echo "Perfect! There are not patch files"
+    exit 0
+fi
+
+for FILE in $FILES
+do
+  REQUEST+=" -F \"data=@$FILE\""
+done
+
+REQUEST+=" -H \"Authorization: $OCTOPATCH_API_TOKEN\" api.octopatch.io/api/pulls/$TRAVIS_REPO_SLUG/$TRAVIS_PULL_REQUEST/$TRAVIS_PULL_REQUEST_SHA"
+eval $REQUEST
\ No newline at end of file
diff --git a/javaparser-core-generators/javaparser-core-generators.iml b/javaparser-core-generators/javaparser-core-generators.iml
deleted file mode 100644
index 7843639..0000000
--- a/javaparser-core-generators/javaparser-core-generators.iml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="javaparser-core" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-core-generators/pom.xml b/javaparser-core-generators/pom.xml
index 58eecf8..739b64b 100644
--- a/javaparser-core-generators/pom.xml
+++ b/javaparser-core-generators/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>javaparser-parent</artifactId>
         <groupId>com.github.javaparser</groupId>
-        <version>3.5.16-SNAPSHOT</version>
+        <version>3.14.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -20,7 +20,7 @@
 
     <profiles>
         <profile>
-            <id>run-core-generators</id>
+            <id>run-generators</id>
             <build>
                 <plugins>
                     <plugin>
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/Generator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/Generator.java
index f7860b0..54d723a 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/Generator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/Generator.java
@@ -7,9 +7,9 @@
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.expr.StringLiteralExpr;
 import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
+import com.github.javaparser.ast.Generated;
 import com.github.javaparser.utils.SourceRoot;
 
-import javax.annotation.Generated;
 import java.util.List;
 
 import static com.github.javaparser.ast.NodeList.toNodeList;
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/NodeGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/NodeGenerator.java
index 18ab60d..2900edd 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/NodeGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/NodeGenerator.java
@@ -1,7 +1,6 @@
 package com.github.javaparser.generator;
 
 import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.CallableDeclaration;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.metamodel.BaseNodeMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
@@ -9,11 +8,6 @@
 import com.github.javaparser.utils.Pair;
 import com.github.javaparser.utils.SourceRoot;
 
-import java.io.IOException;
-import java.util.List;
-
-import static com.github.javaparser.utils.CodeGenerationUtils.f;
-
 /**
  * Makes it easier to generate code in the core AST nodes. The generateNode method will get every node type passed to
  * it, ready for modification.
@@ -24,7 +18,7 @@
     }
 
     public final void generate() throws Exception {
-        Log.info("Running %s", getClass().getSimpleName());
+        Log.info("Running %s", () -> getClass().getSimpleName());
         for (BaseNodeMetaModel nodeMetaModel : JavaParserMetaModel.getNodeMetaModels()) {
             Pair<CompilationUnit, ClassOrInterfaceDeclaration> result = parseNode(nodeMetaModel);
             generateNode(nodeMetaModel, result.a, result.b);
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/VisitorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/VisitorGenerator.java
index 16b5ef4..49f21da 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/VisitorGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/VisitorGenerator.java
@@ -12,7 +12,7 @@
 
 import java.util.Optional;
 
-import static com.github.javaparser.ast.Modifier.PUBLIC;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
 
 /**
  * Makes it easier to generate visitor classes.
@@ -36,7 +36,7 @@
     }
 
     public final void generate() throws Exception {
-        Log.info("Running %s", getClass().getSimpleName());
+        Log.info("Running %s", () -> getClass().getSimpleName());
 
         final CompilationUnit compilationUnit = sourceRoot.tryToParse(pkg, visitorClassName + ".java").getResult().get();
 
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/CoreGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/CoreGenerator.java
index c1aa5f9..73acac1 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/CoreGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/CoreGenerator.java
@@ -1,6 +1,7 @@
 package com.github.javaparser.generator.core;
 
 import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.generator.core.node.*;
 import com.github.javaparser.generator.core.other.TokenKindGenerator;
 import com.github.javaparser.generator.core.visitor.*;
@@ -10,6 +11,8 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.RAW;
+
 /**
  * Generates all generated visitors in the javaparser-core module.
  * Suggested usage is by running the run_core_generators.sh script.
@@ -17,6 +20,7 @@
  */
 public class CoreGenerator {
     private static final ParserConfiguration parserConfiguration = new ParserConfiguration()
+            .setLanguageLevel(RAW)
 //                                .setStoreTokens(false)
 //                                .setAttributeComments(false)
 //                                .setLexicalPreservationEnabled(true)
@@ -31,6 +35,7 @@
         final SourceRoot sourceRoot = new SourceRoot(root, parserConfiguration)
 //                .setPrinter(LexicalPreservingPrinter::print)
                 ;
+        StaticJavaParser.setConfiguration(parserConfiguration);
 
         final Path generatedJavaCcRoot = Paths.get(args[0], "..", "javaparser-core", "target", "generated-sources", "javacc");
         final SourceRoot generatedJavaCcSourceRoot = new SourceRoot(generatedJavaCcRoot, parserConfiguration)
@@ -66,7 +71,7 @@
         new CloneGenerator(sourceRoot).generate();
         new GetMetaModelGenerator(sourceRoot).generate();
         new MainConstructorGenerator(sourceRoot).generate();
-        new FinalGenerator(sourceRoot).generate();
+        new NodeModifierGenerator(sourceRoot).generate();
         new AcceptGenerator(sourceRoot).generate();
         new TokenKindGenerator(sourceRoot, generatedJavaCcSourceRoot).generate();
     }
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/AcceptGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/AcceptGenerator.java
index 9ab2bf3..83df467 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/AcceptGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/AcceptGenerator.java
@@ -9,7 +9,7 @@
 import com.github.javaparser.metamodel.BaseNodeMetaModel;
 import com.github.javaparser.utils.SourceRoot;
 
-import static com.github.javaparser.JavaParser.parseBodyDeclaration;
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
 
 public class AcceptGenerator extends NodeGenerator {
     private final MethodDeclaration genericAccept;
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/CloneGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/CloneGenerator.java
index 6a788b4..8aa1128 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/CloneGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/CloneGenerator.java
@@ -8,7 +8,7 @@
 import com.github.javaparser.metamodel.BaseNodeMetaModel;
 import com.github.javaparser.utils.SourceRoot;
 
-import static com.github.javaparser.JavaParser.parseBodyDeclaration;
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 
 public class CloneGenerator extends NodeGenerator {
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/FinalGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/FinalGenerator.java
deleted file mode 100644
index 8e8cef2..0000000
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/FinalGenerator.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.github.javaparser.generator.core.node;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.generator.NodeGenerator;
-import com.github.javaparser.metamodel.BaseNodeMetaModel;
-import com.github.javaparser.utils.SourceRoot;
-
-public class FinalGenerator extends NodeGenerator {
-    public FinalGenerator(SourceRoot sourceRoot) {
-        super(sourceRoot);
-    }
-
-    @Override
-    protected void generateNode(BaseNodeMetaModel nodeMetaModel, CompilationUnit nodeCu, ClassOrInterfaceDeclaration nodeCoid) {
-        nodeCoid.setFinal(!nodeMetaModel.isAbstract());
-    }
-}
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/GetMetaModelGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/GetMetaModelGenerator.java
index 750c52b..187cec3 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/GetMetaModelGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/GetMetaModelGenerator.java
@@ -8,7 +8,7 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.utils.SourceRoot;
 
-import static com.github.javaparser.JavaParser.parseBodyDeclaration;
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 
 public class GetMetaModelGenerator extends NodeGenerator {
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/MainConstructorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/MainConstructorGenerator.java
index 8f71589..8493521 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/MainConstructorGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/MainConstructorGenerator.java
@@ -12,7 +12,7 @@
 import com.github.javaparser.utils.SeparatedItemStringBuilder;
 import com.github.javaparser.utils.SourceRoot;
 
-import static com.github.javaparser.JavaParser.parseExplicitConstructorInvocationStmt;
+import static com.github.javaparser.StaticJavaParser.parseExplicitConstructorInvocationStmt;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 
 public class MainConstructorGenerator extends NodeGenerator {
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/NodeModifierGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/NodeModifierGenerator.java
new file mode 100644
index 0000000..b2a320f
--- /dev/null
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/NodeModifierGenerator.java
@@ -0,0 +1,20 @@
+package com.github.javaparser.generator.core.node;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.generator.NodeGenerator;
+import com.github.javaparser.metamodel.BaseNodeMetaModel;
+import com.github.javaparser.utils.SourceRoot;
+
+public class NodeModifierGenerator extends NodeGenerator {
+    public NodeModifierGenerator(SourceRoot sourceRoot) {
+        super(sourceRoot);
+    }
+
+    @Override
+    protected void generateNode(BaseNodeMetaModel nodeMetaModel, CompilationUnit nodeCu, ClassOrInterfaceDeclaration nodeCoid) {
+        nodeCoid
+                .setFinal(false)
+                .setPublic(true);
+    }
+}
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/PropertyGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/PropertyGenerator.java
index 9ac69ed..6d34bfd 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/PropertyGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/PropertyGenerator.java
@@ -13,11 +13,15 @@
 import com.github.javaparser.metamodel.PropertyMetaModel;
 import com.github.javaparser.utils.SourceRoot;
 
-import java.util.*;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
-import static com.github.javaparser.JavaParser.parseType;
-import static com.github.javaparser.ast.Modifier.FINAL;
-import static com.github.javaparser.ast.Modifier.PUBLIC;
+import static com.github.javaparser.StaticJavaParser.parseType;
+import static com.github.javaparser.ast.Modifier.Keyword.FINAL;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import static com.github.javaparser.utils.Utils.camelCaseToScreaming;
 
@@ -50,7 +54,7 @@
             return;
         }
 
-        final MethodDeclaration setter = new MethodDeclaration(EnumSet.of(PUBLIC), parseType(property.getContainingNodeMetaModel().getTypeNameGenerified()), property.getSetterMethodName());
+        final MethodDeclaration setter = new MethodDeclaration(createModifierList(PUBLIC), parseType(property.getContainingNodeMetaModel().getTypeNameGenerified()), property.getSetterMethodName());
         if (property.getContainingNodeMetaModel().hasWildcard()) {
             setter.setType(parseType("T"));
         }
@@ -90,7 +94,7 @@
     }
 
     private void generateGetter(BaseNodeMetaModel nodeMetaModel, ClassOrInterfaceDeclaration nodeCoid, PropertyMetaModel property) {
-        final MethodDeclaration getter = new MethodDeclaration(EnumSet.of(PUBLIC), parseType(property.getTypeNameForGetter()), property.getGetterMethodName());
+        final MethodDeclaration getter = new MethodDeclaration(createModifierList(PUBLIC), parseType(property.getTypeNameForGetter()), property.getGetterMethodName());
         final BlockStmt body = getter.getBody().get();
         body.getStatements().clear();
         if (property.isOptional()) {
@@ -107,11 +111,7 @@
         String constantName = camelCaseToScreaming(name.startsWith("is") ? name.substring(2) : name);
         EnumConstantDeclaration enumConstantDeclaration = observablePropertyEnum.addEnumConstant(constantName);
         if (isAttribute) {
-            if (property.isEnumSet()) {
-                enumConstantDeclaration.addArgument("Type.MULTIPLE_ATTRIBUTE");
-            } else {
-                enumConstantDeclaration.addArgument("Type.SINGLE_ATTRIBUTE");
-            }
+            enumConstantDeclaration.addArgument("Type.SINGLE_ATTRIBUTE");
         } else {
             if (property.isNodeList()) {
                 enumConstantDeclaration.addArgument("Type.MULTIPLE_REFERENCE");
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/RemoveMethodGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/RemoveMethodGenerator.java
index 64d5898..d650d49 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/RemoveMethodGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/RemoveMethodGenerator.java
@@ -10,7 +10,7 @@
 import com.github.javaparser.metamodel.BaseNodeMetaModel;
 import com.github.javaparser.metamodel.PropertyMetaModel;
 
-import static com.github.javaparser.JavaParser.*;
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import static com.github.javaparser.utils.Utils.capitalize;
 
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/ReplaceMethodGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/ReplaceMethodGenerator.java
index f1f9d3f..918fd88 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/ReplaceMethodGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/ReplaceMethodGenerator.java
@@ -10,9 +10,8 @@
 import com.github.javaparser.metamodel.PropertyMetaModel;
 import com.github.javaparser.utils.SourceRoot;
 
-import static com.github.javaparser.JavaParser.parseBodyDeclaration;
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
-import static com.github.javaparser.utils.Utils.capitalize;
 
 public class ReplaceMethodGenerator extends NodeGenerator {
     public ReplaceMethodGenerator(SourceRoot sourceRoot) {
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/TypeCastingGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/TypeCastingGenerator.java
index 3a611f4..05d65cd 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/TypeCastingGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/node/TypeCastingGenerator.java
@@ -13,7 +13,7 @@
 import java.util.Set;
 import java.util.function.Consumer;
 
-import static com.github.javaparser.JavaParser.parseBodyDeclaration;
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import static com.github.javaparser.utils.Utils.set;
 
@@ -22,7 +22,7 @@
             JavaParserMetaModel.statementMetaModel,
             JavaParserMetaModel.expressionMetaModel,
             JavaParserMetaModel.typeMetaModel,
-            JavaParserMetaModel.moduleStmtMetaModel,
+            JavaParserMetaModel.moduleDirectiveMetaModel,
             JavaParserMetaModel.bodyDeclarationMetaModel,
             JavaParserMetaModel.commentMetaModel
     );
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/GrammarLetterGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/GrammarLetterGenerator.java
index 9d50bc6..8916fc5 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/GrammarLetterGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/GrammarLetterGenerator.java
@@ -44,6 +44,7 @@
         }
         // Too lazy to remove the final illegal comma.
         System.out.println("]");
+        System.out.println("        | <UNICODE_ESCAPE>");
         System.out.println("  >");
     }
 
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/TokenKindGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/TokenKindGenerator.java
index 5088bc3..d83c322 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/TokenKindGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/other/TokenKindGenerator.java
@@ -9,7 +9,7 @@
 import com.github.javaparser.ast.body.EnumDeclaration;
 import com.github.javaparser.ast.expr.IntegerLiteralExpr;
 import com.github.javaparser.ast.stmt.ReturnStmt;
-import com.github.javaparser.ast.stmt.SwitchEntryStmt;
+import com.github.javaparser.ast.stmt.SwitchEntry;
 import com.github.javaparser.ast.stmt.SwitchStmt;
 import com.github.javaparser.generator.Generator;
 import com.github.javaparser.utils.Log;
@@ -28,7 +28,7 @@
 
     @Override
     public void generate() {
-        Log.info("Running %s", getClass().getSimpleName());
+        Log.info("Running %s", () -> getClass().getSimpleName());
         
         final CompilationUnit javaTokenCu = sourceRoot.parse("com.github.javaparser", "JavaToken.java");
         final ClassOrInterfaceDeclaration javaToken = javaTokenCu.getClassByName("JavaToken").orElseThrow(() -> new AssertionError("Can't find class in java file."));
@@ -38,7 +38,7 @@
         annotateGenerated(kindEnum);
 
         final SwitchStmt valueOfSwitch = kindEnum.findFirst(SwitchStmt.class).orElseThrow(() -> new AssertionError("Can't find valueOf switch."));
-        valueOfSwitch.findAll(SwitchEntryStmt.class).stream().filter(e -> e.getLabel().isPresent()).forEach(Node::remove);
+        valueOfSwitch.findAll(SwitchEntry.class).stream().filter(e -> e.getLabels().isNonEmpty()).forEach(Node::remove);
 
         final CompilationUnit constantsCu = generatedJavaCcSourceRoot.parse("com.github.javaparser", "GeneratedJavaParserConstants.java");
         final ClassOrInterfaceDeclaration constants = constantsCu.getInterfaceByName("GeneratedJavaParserConstants").orElseThrow(() -> new AssertionError("Can't find class in java file."));
@@ -59,7 +59,7 @@
     }
 
     private void generateValueOfEntry(SwitchStmt valueOfSwitch, String name, IntegerLiteralExpr kind) {
-        final SwitchEntryStmt entry = new SwitchEntryStmt(kind, new NodeList<>(new ReturnStmt(name)));
+        final SwitchEntry entry = new SwitchEntry(new NodeList<>(kind), SwitchEntry.Type.STATEMENT_GROUP, new NodeList<>(new ReturnStmt(name)));
         valueOfSwitch.getEntries().addFirst(entry);
     }
 
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/CloneVisitorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/CloneVisitorGenerator.java
index 44a7e9f..c121bc3 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/CloneVisitorGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/CloneVisitorGenerator.java
@@ -4,6 +4,7 @@
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.generator.VisitorGenerator;
+import com.github.javaparser.metamodel.CompilationUnitMetaModel;
 import com.github.javaparser.utils.SeparatedItemStringBuilder;
 import com.github.javaparser.utils.SourceRoot;
 import com.github.javaparser.metamodel.BaseNodeMetaModel;
@@ -53,7 +54,12 @@
         }
 
         body.addStatement(builder.toString());
+        if(node instanceof CompilationUnitMetaModel) {
+            body.addStatement("n.getStorage().ifPresent(s -> r.setStorage(s.getPath(), s.getEncoding()));");
+        }
         body.addStatement("r.setComment(comment);");
+        body.addStatement("n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);");
+        body.addStatement("copyData(n, r);");
         body.addStatement("return r;");
     }
 }
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/HashCodeVisitorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/HashCodeVisitorGenerator.java
index 554dc8d..36556e9 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/HashCodeVisitorGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/HashCodeVisitorGenerator.java
@@ -11,7 +11,7 @@
 
 import java.util.List;
 
-import static com.github.javaparser.JavaParser.parseStatement;
+import static com.github.javaparser.StaticJavaParser.parseStatement;
 
 /**
  * Generates JavaParser's HashCodeVisitor.
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java
index b36d259..e8a9729 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/NoCommentHashCodeVisitorGenerator.java
@@ -1,89 +1,89 @@
-/*

- * 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.generator.core.visitor;

-

-import static com.github.javaparser.JavaParser.parseStatement;

-

-import java.util.List;

-

-import com.github.javaparser.ast.CompilationUnit;

-import com.github.javaparser.ast.body.MethodDeclaration;

-import com.github.javaparser.ast.stmt.BlockStmt;

-import com.github.javaparser.generator.VisitorGenerator;

-import com.github.javaparser.metamodel.BaseNodeMetaModel;

-import com.github.javaparser.metamodel.JavaParserMetaModel;

-import com.github.javaparser.metamodel.PropertyMetaModel;

-import com.github.javaparser.utils.SeparatedItemStringBuilder;

-import com.github.javaparser.utils.SourceRoot;

-

-public class NoCommentHashCodeVisitorGenerator extends VisitorGenerator {

-

-    public NoCommentHashCodeVisitorGenerator(SourceRoot sourceRoot) {

-        super(sourceRoot, "com.github.javaparser.ast.visitor", "NoCommentHashCodeVisitor", "Integer", "Void", true);

-    }

-

-    @Override

-    protected void generateVisitMethodBody(BaseNodeMetaModel node, MethodDeclaration visitMethod,

-                                           CompilationUnit compilationUnit) {

-        visitMethod.getParameters().forEach(p -> p.setFinal(true));

-

-        final BlockStmt body = visitMethod.getBody().get();

-        body.getStatements().clear();

-

-        final SeparatedItemStringBuilder builder = new SeparatedItemStringBuilder("return ", "* 31 +", ";");

-        final List<PropertyMetaModel> propertyMetaModels = node.getAllPropertyMetaModels();

-        if (node.equals(JavaParserMetaModel.lineCommentMetaModel)

-                || node.equals(JavaParserMetaModel.blockCommentMetaModel)

-                || node.equals(JavaParserMetaModel.javadocCommentMetaModel) || propertyMetaModels.isEmpty()) {

-            builder.append("0");

-        } else {

-            for (PropertyMetaModel field : propertyMetaModels) {

-                final String getter = field.getGetterMethodName() + "()";

-                if (field.equals(JavaParserMetaModel.nodeMetaModel.commentPropertyMetaModel)) {

-                    if (propertyMetaModels.size() == 1) {

-                        builder.append("0");

-                        break;

-                    } else

-                        continue;

-                }

-                // Is this field another AST node? Visit it.

-                if (field.getNodeReference().isPresent()) {

-                    if (field.isOptional()) {

-                        builder.append("(n.%s.isPresent()? n.%s.get().accept(this, arg):0)", getter, getter);

-                    } else {

-                        builder.append("(n.%s.accept(this, arg))", getter);

-                    }

-                } else {

-                    Class<?> type = field.getType();

-                    if (type.equals(boolean.class)) {

-                        builder.append("(n.%s?1:0)", getter);

-                    } else if (type.equals(int.class)) {

-                        builder.append("n.%s", getter);

-                    } else {

-                        builder.append("(n.%s.hashCode())", getter);

-                    }

-                }

-            }

-        }

-        body.addStatement(parseStatement(builder.toString()));

-    }

-}

+/*
+ * 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.generator.core.visitor;
+
+import java.util.List;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.generator.VisitorGenerator;
+import com.github.javaparser.metamodel.BaseNodeMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.metamodel.PropertyMetaModel;
+import com.github.javaparser.utils.SeparatedItemStringBuilder;
+import com.github.javaparser.utils.SourceRoot;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+
+public class NoCommentHashCodeVisitorGenerator extends VisitorGenerator {
+
+    public NoCommentHashCodeVisitorGenerator(SourceRoot sourceRoot) {
+        super(sourceRoot, "com.github.javaparser.ast.visitor", "NoCommentHashCodeVisitor", "Integer", "Void", true);
+    }
+
+    @Override
+    protected void generateVisitMethodBody(BaseNodeMetaModel node, MethodDeclaration visitMethod,
+                                           CompilationUnit compilationUnit) {
+        visitMethod.getParameters().forEach(p -> p.setFinal(true));
+
+        final BlockStmt body = visitMethod.getBody().get();
+        body.getStatements().clear();
+
+        final SeparatedItemStringBuilder builder = new SeparatedItemStringBuilder("return ", "* 31 +", ";");
+        final List<PropertyMetaModel> propertyMetaModels = node.getAllPropertyMetaModels();
+        if (node.equals(JavaParserMetaModel.lineCommentMetaModel)
+                || node.equals(JavaParserMetaModel.blockCommentMetaModel)
+                || node.equals(JavaParserMetaModel.javadocCommentMetaModel) || propertyMetaModels.isEmpty()) {
+            builder.append("0");
+        } else {
+            for (PropertyMetaModel field : propertyMetaModels) {
+                final String getter = field.getGetterMethodName() + "()";
+                if (field.equals(JavaParserMetaModel.nodeMetaModel.commentPropertyMetaModel)) {
+                    if (propertyMetaModels.size() == 1) {
+                        builder.append("0");
+                        break;
+                    } else
+                        continue;
+                }
+                // Is this field another AST node? Visit it.
+                if (field.getNodeReference().isPresent()) {
+                    if (field.isOptional()) {
+                        builder.append("(n.%s.isPresent()? n.%s.get().accept(this, arg):0)", getter, getter);
+                    } else {
+                        builder.append("(n.%s.accept(this, arg))", getter);
+                    }
+                } else {
+                    Class<?> type = field.getType();
+                    if (type.equals(boolean.class)) {
+                        builder.append("(n.%s?1:0)", getter);
+                    } else if (type.equals(int.class)) {
+                        builder.append("n.%s", getter);
+                    } else {
+                        builder.append("(n.%s.hashCode())", getter);
+                    }
+                }
+            }
+        }
+        body.addStatement(parseStatement(builder.toString()));
+    }
+}
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityEqualsVisitorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityEqualsVisitorGenerator.java
index 3c182fc..053fd44 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityEqualsVisitorGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityEqualsVisitorGenerator.java
@@ -5,11 +5,8 @@
 import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.generator.VisitorGenerator;
 import com.github.javaparser.metamodel.BaseNodeMetaModel;
-import com.github.javaparser.metamodel.PropertyMetaModel;
 import com.github.javaparser.utils.SourceRoot;
 
-import static com.github.javaparser.utils.CodeGenerationUtils.f;
-
 /**
  * Generates JavaParser's ObjectIdentityEqualsVisitor.
  */
diff --git a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityHashCodeVisitorGenerator.java b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityHashCodeVisitorGenerator.java
index 88eb3e7..8e320d3 100644
--- a/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityHashCodeVisitorGenerator.java
+++ b/javaparser-core-generators/src/main/java/com/github/javaparser/generator/core/visitor/ObjectIdentityHashCodeVisitorGenerator.java
@@ -5,14 +5,8 @@
 import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.generator.VisitorGenerator;
 import com.github.javaparser.metamodel.BaseNodeMetaModel;
-import com.github.javaparser.metamodel.PropertyMetaModel;
-import com.github.javaparser.utils.SeparatedItemStringBuilder;
 import com.github.javaparser.utils.SourceRoot;
 
-import java.util.List;
-
-import static com.github.javaparser.JavaParser.parseStatement;
-
 /**
  * Generates JavaParser's ObjectIdentityHashCodeVisitor.
  */
diff --git a/javaparser-core-metamodel-generator/pom.xml b/javaparser-core-metamodel-generator/pom.xml
new file mode 100644
index 0000000..4d63968
--- /dev/null
+++ b/javaparser-core-metamodel-generator/pom.xml
@@ -0,0 +1,63 @@
+<?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.14.10-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>javaparser-core-metamodel-generator</artifactId>
+    <description>The tool that generates the code in the javaparser-metamodel module</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.github.javaparser</groupId>
+            <artifactId>javaparser-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <!-- no need to release this module -->
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>run-generators</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>generate-javaparser-metamodel</id>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <classpathScope>test</classpathScope>
+                            <mainClass>com.github.javaparser.generator.metamodel.MetaModelGenerator</mainClass>
+                            <arguments>
+                                <argument>${project.basedir}</argument>
+                            </arguments>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/AstTypeAnalysis.java b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/AstTypeAnalysis.java
new file mode 100644
index 0000000..ca4f3f3
--- /dev/null
+++ b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/AstTypeAnalysis.java
@@ -0,0 +1,51 @@
+package com.github.javaparser.generator.metamodel;
+
+import com.github.javaparser.ast.NodeList;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Optional;
+
+import static java.lang.reflect.Modifier.isAbstract;
+
+/**
+ * A hacky thing that collects flags we need from AST types to generate the metamodel.
+ */
+class AstTypeAnalysis {
+    final boolean isAbstract;
+    boolean isOptional = false;
+    boolean isNodeList = false;
+    boolean isSelfType = false;
+    Class<?> innerType;
+
+    AstTypeAnalysis(Type type) {
+        if (type instanceof Class<?>) {
+            TypeVariable<? extends Class<?>>[] typeParameters = ((Class<?>) type).getTypeParameters();
+            if (typeParameters.length > 0) {
+                isSelfType = true;
+            }
+        } else {
+            while (type instanceof ParameterizedType) {
+                ParameterizedType t = (ParameterizedType) type;
+                Type currentOuterType = t.getRawType();
+                if (currentOuterType == NodeList.class) {
+                    isNodeList = true;
+                }
+                if (currentOuterType == Optional.class) {
+                    isOptional = true;
+                }
+
+                if (t.getActualTypeArguments()[0] instanceof WildcardType) {
+                    type = t.getRawType();
+                    isSelfType = true;
+                    break;
+                }
+                type = t.getActualTypeArguments()[0];
+            }
+        }
+        innerType = (Class<?>) type;
+        isAbstract = isAbstract(innerType.getModifiers());
+    }
+}
diff --git a/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializeConstructorParametersStatementsGenerator.java b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializeConstructorParametersStatementsGenerator.java
new file mode 100644
index 0000000..ef46378
--- /dev/null
+++ b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializeConstructorParametersStatementsGenerator.java
@@ -0,0 +1,58 @@
+package com.github.javaparser.generator.metamodel;
+
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.stmt.Statement;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+import static com.github.javaparser.generator.metamodel.MetaModelGenerator.nodeMetaModelFieldName;
+import static com.github.javaparser.generator.metamodel.MetaModelGenerator.propertyMetaModelFieldName;
+import static com.github.javaparser.utils.CodeGenerationUtils.f;
+
+class InitializeConstructorParametersStatementsGenerator {
+    void generate(Class<? extends Node> nodeClass, NodeList<Statement> initializeConstructorParametersStatements) {
+        if (nodeClass == Node.class) {
+            return;
+        }
+        Constructor<?> constructor = findAllFieldsConstructor(nodeClass);
+        for (java.lang.reflect.Parameter parameter : constructor.getParameters()) {
+            Field field = findFieldInClass(nodeClass, parameter.getName());
+
+            String addFieldStatement = f("%s.getConstructorParameters().add(%s.%s);",
+                    nodeMetaModelFieldName(nodeClass),
+                    nodeMetaModelFieldName(field.getDeclaringClass()),
+                    propertyMetaModelFieldName(field));
+
+            initializeConstructorParametersStatements.add(parseStatement(addFieldStatement));
+        }
+    }
+
+    private Field findFieldInClass(Class<?> nodeClass, String name) {
+        Class<?> searchClass = nodeClass;
+        do {
+            for (Field field : searchClass.getDeclaredFields()) {
+                if (field.getName().equals(name)) {
+                    return field;
+                }
+            }
+            searchClass = searchClass.getSuperclass();
+        } while (searchClass != null);
+        throw new AssertionError(f("Couldn't find constructor parameter %s as a field, class %s", name, nodeClass.getSimpleName()));
+    }
+
+    private Constructor<?> findAllFieldsConstructor(Class<? extends Node> nodeClass) {
+        for (Constructor<?> constructor : nodeClass.getDeclaredConstructors()) {
+            for (Annotation annotation : constructor.getAnnotations()) {
+                if (annotation.annotationType() == AllFieldsConstructor.class) {
+                    return constructor;
+                }
+            }
+        }
+        throw new AssertionError(f("Node class %s has no constructor annotated with @AllFieldsConstructor", nodeClass.getSimpleName()));
+    }
+}
diff --git a/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializePropertyMetaModelsStatementsGenerator.java b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializePropertyMetaModelsStatementsGenerator.java
new file mode 100644
index 0000000..22200de
--- /dev/null
+++ b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializePropertyMetaModelsStatementsGenerator.java
@@ -0,0 +1,77 @@
+package com.github.javaparser.generator.metamodel;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.metamodel.NonEmptyProperty;
+import com.github.javaparser.metamodel.OptionalProperty;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.generator.metamodel.MetaModelGenerator.isNode;
+import static com.github.javaparser.generator.metamodel.MetaModelGenerator.nodeMetaModelName;
+import static com.github.javaparser.utils.CodeGenerationUtils.*;
+import static com.github.javaparser.utils.Utils.decapitalize;
+
+class InitializePropertyMetaModelsStatementsGenerator {
+    void generate(Field field, ClassOrInterfaceDeclaration nodeMetaModelClass, String nodeMetaModelFieldName, NodeList<Statement> initializePropertyMetaModelsStatements) {
+        final AstTypeAnalysis fieldTypeAnalysis = new AstTypeAnalysis(field.getGenericType());
+
+        final Class<?> fieldType = fieldTypeAnalysis.innerType;
+        final String typeName = fieldType.getTypeName().replace('$', '.');
+        final String propertyMetaModelFieldName = field.getName() + "PropertyMetaModel";
+        nodeMetaModelClass.addField("PropertyMetaModel", propertyMetaModelFieldName, PUBLIC);
+        final String propertyInitializer = f("new PropertyMetaModel(%s, \"%s\", %s.class, %s, %s, %s, %s, %s)",
+                nodeMetaModelFieldName,
+                field.getName(),
+                typeName,
+                optionalOf(decapitalize(nodeMetaModelName(fieldType)), isNode(fieldType)),
+                isOptional(field),
+                isNonEmpty(field),
+                fieldTypeAnalysis.isNodeList,
+                fieldTypeAnalysis.isSelfType);
+        final String fieldSetting = f("%s.%s=%s;", nodeMetaModelFieldName, propertyMetaModelFieldName, propertyInitializer);
+        final String fieldAddition = f("%s.getDeclaredPropertyMetaModels().add(%s.%s);", nodeMetaModelFieldName, nodeMetaModelFieldName, propertyMetaModelFieldName);
+
+        initializePropertyMetaModelsStatements.add(parseStatement(fieldSetting));
+        initializePropertyMetaModelsStatements.add(parseStatement(fieldAddition));
+    }
+
+    void generateDerivedProperty(Method method, ClassOrInterfaceDeclaration nodeMetaModelClass, String nodeMetaModelFieldName, NodeList<Statement> initializePropertyMetaModelsStatements) {
+        final AstTypeAnalysis returnTypeAnalysis = new AstTypeAnalysis(method.getGenericReturnType());
+
+        final Class<?> innermostReturnType = returnTypeAnalysis.innerType;
+        final String typeName = innermostReturnType.getTypeName().replace('$', '.');
+        final String propertyMetaModelFieldName = getterToPropertyName(method.getName()) + "PropertyMetaModel";
+        nodeMetaModelClass.addField("PropertyMetaModel", propertyMetaModelFieldName, PUBLIC);
+        final String propertyInitializer = f("new PropertyMetaModel(%s, \"%s\", %s.class, %s, %s, %s, %s, %s)",
+                nodeMetaModelFieldName,
+                getterToPropertyName(method.getName()),
+                typeName,
+                optionalOf(decapitalize(nodeMetaModelName(innermostReturnType)), isNode(innermostReturnType)),
+                returnTypeAnalysis.isOptional,
+                isNonEmpty(method),
+                returnTypeAnalysis.isNodeList,
+                returnTypeAnalysis.isSelfType);
+        final String fieldSetting = f("%s.%s=%s;", nodeMetaModelFieldName, propertyMetaModelFieldName, propertyInitializer);
+        final String fieldAddition = f("%s.getDerivedPropertyMetaModels().add(%s.%s);", nodeMetaModelFieldName, nodeMetaModelFieldName, propertyMetaModelFieldName);
+
+        initializePropertyMetaModelsStatements.add(parseStatement(fieldSetting));
+        initializePropertyMetaModelsStatements.add(parseStatement(fieldAddition));
+    }
+
+    private boolean isNonEmpty(Field field) {
+        return field.isAnnotationPresent(NonEmptyProperty.class);
+    }
+
+    private boolean isNonEmpty(Method method) {
+        return method.isAnnotationPresent(NonEmptyProperty.class);
+    }
+
+    private boolean isOptional(Field field) {
+        return field.isAnnotationPresent(OptionalProperty.class);
+    }
+}
diff --git a/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java
new file mode 100644
index 0000000..61fcfd9
--- /dev/null
+++ b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java
@@ -0,0 +1,214 @@
+package com.github.javaparser.generator.metamodel;
+
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.*;
+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.modules.*;
+import com.github.javaparser.ast.stmt.*;
+import com.github.javaparser.ast.type.*;
+import com.github.javaparser.printer.PrettyPrinter;
+import com.github.javaparser.printer.PrettyPrinterConfiguration;
+import com.github.javaparser.utils.SourceRoot;
+
+import java.lang.reflect.Field;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import static com.github.javaparser.utils.Utils.decapitalize;
+
+public class MetaModelGenerator {
+    static final String BASE_NODE_META_MODEL = "BaseNodeMetaModel";
+    private static List<Class<? extends Node>> ALL_NODE_CLASSES = new ArrayList<Class<? extends Node>>() {{
+        /* Base classes go first, so we don't have to do any sorting to make sure
+         generated classes can refer to their base generated classes without
+         being afraid those are not initialized yet. */
+        add(Node.class);
+
+        add(BodyDeclaration.class);
+        add(CallableDeclaration.class);
+        add(Statement.class);
+        add(Expression.class);
+        add(Type.class);
+
+        add(AnnotationExpr.class);
+        add(TypeDeclaration.class);
+        add(ReferenceType.class);
+
+        add(LiteralExpr.class);
+        add(LiteralStringValueExpr.class);
+        add(StringLiteralExpr.class);
+
+        add(ModuleDeclaration.class);
+        add(ModuleDirective.class);
+
+        //
+        add(ArrayCreationLevel.class);
+        add(CompilationUnit.class);
+        add(PackageDeclaration.class);
+        add(Modifier.class);
+
+        add(AnnotationDeclaration.class);
+        add(AnnotationMemberDeclaration.class);
+        add(ClassOrInterfaceDeclaration.class);
+        add(ConstructorDeclaration.class);
+        add(EnumConstantDeclaration.class);
+        add(EnumDeclaration.class);
+        add(FieldDeclaration.class);
+        add(InitializerDeclaration.class);
+        add(MethodDeclaration.class);
+        add(Parameter.class);
+        add(ReceiverParameter.class);
+        add(VariableDeclarator.class);
+
+        add(Comment.class);
+        add(BlockComment.class);
+        add(JavadocComment.class);
+        add(LineComment.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(FieldAccessExpr.class);
+        add(InstanceOfExpr.class);
+        add(IntegerLiteralExpr.class);
+        add(LambdaExpr.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(SuperExpr.class);
+        add(ThisExpr.class);
+        add(TypeExpr.class);
+        add(UnaryExpr.class);
+        add(VariableDeclarationExpr.class);
+        add(SwitchExpr.class);
+
+        add(ImportDeclaration.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(SwitchEntry.class);
+        add(SwitchStmt.class);
+        add(SynchronizedStmt.class);
+        add(ThrowStmt.class);
+        add(TryStmt.class);
+        add(LocalClassDeclarationStmt.class);
+        add(WhileStmt.class);
+        add(UnparsableStmt.class);
+
+        add(ArrayType.class);
+        add(ClassOrInterfaceType.class);
+        add(IntersectionType.class);
+        add(PrimitiveType.class);
+        add(TypeParameter.class);
+        add(UnionType.class);
+        add(UnknownType.class);
+        add(VoidType.class);
+        add(WildcardType.class);
+        add(VarType.class);
+
+        add(ModuleRequiresDirective.class);
+        add(ModuleExportsDirective.class);
+        add(ModuleProvidesDirective.class);
+        add(ModuleUsesDirective.class);
+        add(ModuleOpensDirective.class);
+    }};
+
+    static String METAMODEL_PACKAGE = "com.github.javaparser.metamodel";
+
+    public static void main(String[] args) throws NoSuchMethodException {
+        if (args.length != 1) {
+            throw new RuntimeException("Need 1 parameter: the JavaParser source checkout root directory.");
+        }
+        final Path root = Paths.get(args[0], "..", "javaparser-core", "src", "main", "java");
+        final ParserConfiguration parserConfiguration = new ParserConfiguration()
+                .setLanguageLevel(ParserConfiguration.LanguageLevel.RAW)
+                .setStoreTokens(false);
+        final SourceRoot sourceRoot = new SourceRoot(root, parserConfiguration);
+        sourceRoot.setPrinter(new PrettyPrinter(new PrettyPrinterConfiguration().setEndOfLineCharacter("\n"))::print);
+        StaticJavaParser.setConfiguration(parserConfiguration);
+
+        new MetaModelGenerator().run(sourceRoot);
+
+        sourceRoot.saveAll();
+    }
+
+    private void run(SourceRoot sourceRoot) throws NoSuchMethodException {
+        final CompilationUnit javaParserMetaModel = sourceRoot.parse(METAMODEL_PACKAGE, "JavaParserMetaModel.java");
+
+        generateNodeMetaModels(javaParserMetaModel, sourceRoot);
+    }
+
+    private void generateNodeMetaModels(CompilationUnit javaParserMetaModelCu, SourceRoot sourceRoot) throws NoSuchMethodException {
+        final ClassOrInterfaceDeclaration metaModelCoid = javaParserMetaModelCu.getClassByName("JavaParserMetaModel").get();
+        final NodeList<Statement> initializeNodeMetaModelsStatements = metaModelCoid.getMethodsByName("initializeNodeMetaModels").get(0).getBody().get().getStatements();
+        final NodeList<Statement> initializePropertyMetaModelsStatements = metaModelCoid.getMethodsByName("initializePropertyMetaModels").get(0).getBody().get().getStatements();
+        final NodeList<Statement> initializeConstructorParametersStatements = metaModelCoid.getMethodsByName("initializeConstructorParameters").get(0).getBody().get().getStatements();
+        initializeNodeMetaModelsStatements.clear();
+        initializePropertyMetaModelsStatements.clear();
+        initializeConstructorParametersStatements.clear();
+
+        metaModelCoid.getFields().stream().filter(f -> f.getVariable(0).getNameAsString().endsWith("MetaModel")).forEach(Node::remove);
+        final NodeMetaModelGenerator nodeMetaModelGenerator = new NodeMetaModelGenerator();
+        for (Class<? extends Node> nodeClass : ALL_NODE_CLASSES) {
+            nodeMetaModelGenerator.generate(nodeClass, metaModelCoid, initializeNodeMetaModelsStatements, initializePropertyMetaModelsStatements, initializeConstructorParametersStatements, sourceRoot);
+        }
+
+        initializeNodeMetaModelsStatements.sort(Comparator.comparing(Node::toString));
+    }
+
+    static boolean isNode(Class<?> c) {
+        return Node.class.isAssignableFrom(c);
+    }
+
+    static String nodeMetaModelName(Class<?> c) {
+        return c.getSimpleName() + "MetaModel";
+    }
+
+    static String propertyMetaModelFieldName(Field field) {
+        return field.getName() + "PropertyMetaModel";
+    }
+
+    static String nodeMetaModelFieldName(Class<?> nodeClass) {
+        return decapitalize(nodeMetaModelName(nodeClass));
+    }
+
+}
diff --git a/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/NodeMetaModelGenerator.java b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/NodeMetaModelGenerator.java
new file mode 100644
index 0000000..e800159
--- /dev/null
+++ b/javaparser-core-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/NodeMetaModelGenerator.java
@@ -0,0 +1,117 @@
+package com.github.javaparser.generator.metamodel;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.metamodel.DerivedProperty;
+import com.github.javaparser.metamodel.InternalProperty;
+import com.github.javaparser.utils.SourceRoot;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.ast.Modifier.Keyword.*;
+import static com.github.javaparser.generator.metamodel.MetaModelGenerator.*;
+import static com.github.javaparser.utils.CodeGenerationUtils.f;
+import static com.github.javaparser.utils.CodeGenerationUtils.optionalOf;
+import static com.github.javaparser.utils.Utils.decapitalize;
+
+public class NodeMetaModelGenerator {
+    private final InitializePropertyMetaModelsStatementsGenerator initializePropertyMetaModelsStatementsGenerator = new InitializePropertyMetaModelsStatementsGenerator();
+    private final InitializeConstructorParametersStatementsGenerator initializeConstructorParametersStatementsGenerator = new InitializeConstructorParametersStatementsGenerator();
+
+    public void generate(Class<? extends Node> nodeClass, ClassOrInterfaceDeclaration metaModelCoid, NodeList<Statement> initializeNodeMetaModelsStatements, NodeList<Statement> initializePropertyMetaModelsStatements, NodeList<Statement> initializeConstructorParametersStatements, SourceRoot sourceRoot) throws NoSuchMethodException {
+        final String className = nodeMetaModelName(nodeClass);
+        final String nodeMetaModelFieldName = decapitalize(className);
+        metaModelCoid.getFieldByName(nodeMetaModelFieldName).ifPresent(Node::remove);
+
+        final FieldDeclaration nodeField = metaModelCoid.addField(className, nodeMetaModelFieldName, PUBLIC, STATIC, FINAL);
+
+        final Class<?> superclass = nodeClass.getSuperclass();
+        final String superNodeMetaModel = nodeMetaModelName(superclass);
+
+        boolean isRootNode = !isNode(superclass);
+        nodeField.getVariable(0).setInitializer(parseExpression(f("new %s(%s)",
+                className,
+                optionalOf(decapitalize(superNodeMetaModel), !isRootNode))));
+
+        initializeNodeMetaModelsStatements.add(parseStatement(f("nodeMetaModels.add(%s);", nodeMetaModelFieldName)));
+
+        final CompilationUnit classMetaModelJavaFile = new CompilationUnit(METAMODEL_PACKAGE);
+        classMetaModelJavaFile.addImport("java.util.Optional");
+        sourceRoot.add(METAMODEL_PACKAGE, className + ".java", classMetaModelJavaFile);
+        final ClassOrInterfaceDeclaration nodeMetaModelClass = classMetaModelJavaFile.addClass(className, PUBLIC);
+        if (isRootNode) {
+            nodeMetaModelClass.addExtendedType(BASE_NODE_META_MODEL);
+        } else {
+            nodeMetaModelClass.addExtendedType(superNodeMetaModel);
+        }
+
+        final AstTypeAnalysis typeAnalysis = new AstTypeAnalysis(nodeClass);
+
+        final ConstructorDeclaration classMMConstructor = nodeMetaModelClass
+                .addConstructor()
+                .addParameter("Optional<" + BASE_NODE_META_MODEL + ">", "super" + BASE_NODE_META_MODEL);
+        classMMConstructor
+                .getBody()
+                .addStatement(parseExplicitConstructorInvocationStmt(f("super(super%s, %s.class, \"%s\", \"%s\", %s, %s);",
+                        BASE_NODE_META_MODEL,
+                        nodeClass.getName(),
+                        nodeClass.getSimpleName(),
+                        nodeClass.getPackage().getName(),
+                        typeAnalysis.isAbstract,
+                        typeAnalysis.isSelfType)));
+
+        if (typeAnalysis.isAbstract) {
+            classMetaModelJavaFile.addImport(Node.class);
+            nodeMetaModelClass.addMember(parseBodyDeclaration(f(
+                    "protected %s(Optional<BaseNodeMetaModel> superNodeMetaModel, Class<? extends Node> type, String name, String packageName, boolean isAbstract, boolean hasWildcard) {" +
+                            "super(superNodeMetaModel, type, name, packageName, isAbstract, hasWildcard);" +
+                            " }",
+                    className)));
+        }
+
+        final List<Field> fields = new ArrayList<>(Arrays.asList(nodeClass.getDeclaredFields()));
+        fields.sort(Comparator.comparing(Field::getName));
+        for (Field field : fields) {
+            if (fieldShouldBeIgnored(field)) {
+                continue;
+            }
+
+            initializePropertyMetaModelsStatementsGenerator.generate(field, nodeMetaModelClass, nodeMetaModelFieldName, initializePropertyMetaModelsStatements);
+        }
+        final List<Method> methods = new ArrayList<>(Arrays.asList(nodeClass.getMethods()));
+        methods.sort(Comparator.comparing(Method::getName));
+        for (Method method : methods) {
+            if (method.isAnnotationPresent(DerivedProperty.class)) {
+                initializePropertyMetaModelsStatementsGenerator.generateDerivedProperty(method, nodeMetaModelClass, nodeMetaModelFieldName, initializePropertyMetaModelsStatements);
+            }
+        }
+
+        initializeConstructorParametersStatementsGenerator.generate(nodeClass, initializeConstructorParametersStatements);
+
+        moveStaticInitializeToTheEndOfTheClassBecauseWeNeedTheFieldsToInitializeFirst(metaModelCoid);
+    }
+
+    private void moveStaticInitializeToTheEndOfTheClassBecauseWeNeedTheFieldsToInitializeFirst(ClassOrInterfaceDeclaration metaModelCoid) {
+        for (BodyDeclaration<?> m : metaModelCoid.getMembers()) {
+            if (m instanceof InitializerDeclaration) {
+                m.remove();
+                metaModelCoid.addMember(m);
+                return;
+            }
+        }
+    }
+
+    private boolean fieldShouldBeIgnored(Field reflectionField) {
+        return java.lang.reflect.Modifier.isStatic(reflectionField.getModifiers()) ||
+                reflectionField.isAnnotationPresent(InternalProperty.class);
+    }
+}
diff --git a/javaparser-core-serialization/pom.xml b/javaparser-core-serialization/pom.xml
new file mode 100644
index 0000000..23e7655
--- /dev/null
+++ b/javaparser-core-serialization/pom.xml
@@ -0,0 +1,71 @@
+<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.14.10-SNAPSHOT</version>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>javaparser-core-serialization</artifactId>
+	<description>Serializers for the JavaParser AST.</description>
+
+	<licenses>
+		<license>
+			<name>GNU Lesser General Public License</name>
+			<url>http://www.gnu.org/licenses/lgpl-3.0.html</url>
+			<distribution>repo</distribution>
+		</license>
+		<license>
+			<name>Apache License, Version 2.0</name>
+			<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+			<distribution>repo</distribution>
+			<comments>A business-friendly OSS license</comments>
+		</license>
+	</licenses>
+
+	<properties>
+		<java.version>1.8</java.version>
+		<build.timestamp>${maven.build.timestamp}</build.timestamp>
+	</properties>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifestEntries>
+							<Automatic-Module-Name>com.github.javaparser.core.serialization</Automatic-Module-Name>
+						</manifestEntries>
+					</archive>
+				</configuration>
+			</plugin>
+
+		</plugins>
+	</build>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter-engine</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.github.javaparser</groupId>
+			<artifactId>javaparser-core</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>javax.json</groupId>
+			<artifactId>javax.json-api</artifactId>
+			<version>1.1.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.glassfish</groupId>
+			<artifactId>javax.json</artifactId>
+			<version>1.1.4</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>
diff --git a/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonDeserializer.java b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonDeserializer.java
new file mode 100644
index 0000000..d77e127
--- /dev/null
+++ b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonDeserializer.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2018 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.serialization;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.comments.Comment;
+import com.github.javaparser.metamodel.BaseNodeMetaModel;
+import com.github.javaparser.metamodel.PropertyMetaModel;
+import com.github.javaparser.utils.Log;
+
+import javax.json.*;
+import java.util.*;
+
+import static com.github.javaparser.ast.NodeList.toNodeList;
+import static com.github.javaparser.metamodel.JavaParserMetaModel.getNodeMetaModel;
+import static com.github.javaparser.serialization.JavaParserJsonSerializer.*;
+
+/**
+ * Deserializes the JSON file that was built by {@link JavaParserJsonSerializer}.
+ */
+public class JavaParserJsonDeserializer {
+    /**
+     * Deserializes json, contained by JsonReader, into AST node.
+     * The root node and all its child nodes will be deserialized.
+     * @param reader json-p reader (object-level reader, <a href="https://javaee.github.io/jsonp/">see their docs</a>)
+     * @return the root level deserialized node
+     */
+    public Node deserializeObject(JsonReader reader) {
+        Log.info("Deserializing JSON to Node.");
+        JsonObject jsonObject = reader.readObject();
+        return deserializeObject(jsonObject);
+    }
+
+    /**
+     * Recursive depth-first deserializing method that creates a Node instance from JsonObject.
+     *
+     * @param nodeJson json object at current level containg values as properties
+     * @return deserialized node including all children.
+     * @implNote the Node instance will be constructed by the properties defined in the meta model.
+     *           Non meta properties will be set after Node is instantiated.
+     * @implNote comment is included in the propertyKey meta model, but not set when constructing the Node instance.
+     *           That is, comment is not included in the constructor propertyKey list, and therefore needs to be set
+     *           after constructing the node.
+     *           See {@link com.github.javaparser.metamodel.BaseNodeMetaModel#construct(Map)} how the node is contructed
+     */
+    private Node deserializeObject(JsonObject nodeJson) {
+        try {
+            String serializedNodeType = nodeJson.getString(JsonNode.CLASS.propertyKey);
+            BaseNodeMetaModel nodeMetaModel = getNodeMetaModel(Class.forName(serializedNodeType))
+                    .orElseThrow(() -> new IllegalStateException("Trying to deserialize an unknown node type: " + serializedNodeType));
+            Map<String, Object> parameters = new HashMap<>();
+            Map<String, JsonValue> deferredJsonValues = new HashMap<>();
+
+            for (String name : nodeJson.keySet()) {
+                if (name.equals(JsonNode.CLASS.propertyKey)) {
+                    continue;
+                }
+
+                Optional<PropertyMetaModel> optionalPropertyMetaModel = nodeMetaModel.getAllPropertyMetaModels().stream()
+                        .filter(mm -> mm.getName().equals(name))
+                        .findFirst();
+                if (!optionalPropertyMetaModel.isPresent()) {
+                    deferredJsonValues.put(name, nodeJson.get(name));
+                    continue;
+                }
+
+                PropertyMetaModel propertyMetaModel = optionalPropertyMetaModel.get();
+                if (propertyMetaModel.isNodeList()) {
+                    JsonArray nodeListJson = nodeJson.getJsonArray(name);
+                    parameters.put(name, deserializeNodeList(nodeListJson));
+                } else if (propertyMetaModel.isNode()) {
+                    parameters.put(name, deserializeObject(nodeJson.getJsonObject(name)));
+                } else {
+                    Class<?> type = propertyMetaModel.getType();
+                    if (type == String.class) {
+                        parameters.put(name, nodeJson.getString(name));
+                    } else if (type == boolean.class) {
+                        parameters.put(name, Boolean.parseBoolean(nodeJson.getString(name)));
+                    } else if (Enum.class.isAssignableFrom(type)) {
+                        parameters.put(name, Enum.valueOf((Class<? extends Enum>) type, nodeJson.getString(name)));
+                    } else {
+                        throw new IllegalStateException("Don't know how to convert: " + type);
+                    }
+                }
+            }
+
+            Node node = nodeMetaModel.construct(parameters);
+            // COMMENT is in the propertyKey meta model, but not required as constructor parameter.
+            // Set it after construction
+            if (parameters.containsKey(JsonNode.COMMENT.propertyKey)) {
+                node.setComment((Comment)parameters.get(JsonNode.COMMENT.propertyKey));
+            }
+
+            for (String name : deferredJsonValues.keySet()) {
+                if (!readNonMetaProperties(name, deferredJsonValues.get(name), node)) {
+                    throw new IllegalStateException("Unknown propertyKey: " + nodeMetaModel.getQualifiedClassName() + "." + name);
+                }
+            }
+            setSymbolResolverIfCompilationUnit(node);
+
+            return node;
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private NodeList<?> deserializeNodeList(JsonArray nodeListJson) {
+        return nodeListJson.stream().map(nodeJson -> deserializeObject((JsonObject) nodeJson)).collect(toNodeList());
+    }
+
+    /**
+     * Reads properties from json not included in meta model (i.e., RANGE and TOKEN_RANGE).
+     * When read, it sets the deserialized value to the node instance.
+     * @param name propertyKey name for json value
+     * @param jsonValue json value that needs to be deserialized for this propertyKey
+     * @param node instance to which the deserialized value will be set to
+     * @return true if propertyKey is read from json and set to Node instance
+     */
+    protected boolean readNonMetaProperties(String name, JsonValue jsonValue, Node node) {
+        return readRange(name, jsonValue, node)
+                || readTokenRange(name, jsonValue, node);
+    }
+
+    protected boolean readRange(String name, JsonValue jsonValue, Node node) {
+        if (name.equals(JsonNode.RANGE.propertyKey)) {
+            JsonObject jsonObject = (JsonObject)jsonValue;
+            Position begin = new Position(
+                    jsonObject.getInt(JsonRange.BEGIN_LINE.propertyKey),
+                    jsonObject.getInt(JsonRange.BEGIN_COLUMN.propertyKey)
+            );
+            Position end = new Position(
+                    jsonObject.getInt(JsonRange.END_LINE.propertyKey),
+                    jsonObject.getInt(JsonRange.END_COLUMN.propertyKey)
+            );
+            node.setRange(new Range(begin, end));
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean readTokenRange(String name, JsonValue jsonValue, Node node) {
+        if (name.equals(JsonNode.TOKEN_RANGE.propertyKey)) {
+            JsonObject jsonObject = (JsonObject)jsonValue;
+            JavaToken begin = readToken(
+                    JsonTokenRange.BEGIN_TOKEN.propertyKey, jsonObject
+            );
+            JavaToken end = readToken(
+                    JsonTokenRange.END_TOKEN.propertyKey, jsonObject
+            );
+            node.setTokenRange(new TokenRange(begin, end));
+            return true;
+        }
+        return false;
+    }
+
+    protected JavaToken readToken(String name, JsonObject jsonObject) {
+        JsonObject tokenJson = jsonObject.getJsonObject(name);
+        return new JavaToken(
+                tokenJson.getInt(JsonToken.KIND.propertyKey),
+                tokenJson.getString(JsonToken.TEXT.propertyKey)
+        );
+    }
+
+    /**
+     * This method sets symbol resolver to Node if it is an instance of CompilationUnit
+     * and a SymbolResolver is configured in the static configuration. This is necessary to be able to resolve symbols
+     * within the cu after deserialization. Normally, when parsing java with JavaParser, the symbol resolver is injected
+     * to the cu as a data element with key SYMBOL_RESOLVER_KEY.
+     * @param node instance to which symbol resolver will be set to when instance of a Compilation Unit
+     * @see com.github.javaparser.ast.Node#SYMBOL_RESOLVER_KEY
+     * @see com.github.javaparser.ParserConfiguration#ParserConfiguration()
+     */
+    private void setSymbolResolverIfCompilationUnit(Node node) {
+        if (node instanceof CompilationUnit && StaticJavaParser.getConfiguration().getSymbolResolver().isPresent()) {
+            CompilationUnit cu = (CompilationUnit)node;
+            cu.setData(Node.SYMBOL_RESOLVER_KEY, StaticJavaParser.getConfiguration().getSymbolResolver().get());
+        }
+    }
+
+
+}
diff --git a/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonSerializer.java b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonSerializer.java
new file mode 100644
index 0000000..743b57d
--- /dev/null
+++ b/javaparser-core-serialization/src/main/java/com/github/javaparser/serialization/JavaParserJsonSerializer.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2018 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.serialization;
+
+import com.github.javaparser.JavaToken;
+import com.github.javaparser.Range;
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.metamodel.BaseNodeMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.metamodel.PropertyMetaModel;
+import com.github.javaparser.utils.Log;
+
+import javax.json.stream.JsonGenerator;
+
+import static com.github.javaparser.utils.Utils.decapitalize;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Serializes an AST or a partial AST to JSON.
+ */
+public class JavaParserJsonSerializer {
+
+    /**
+     * Serializes node and all its children into json. Any node siblings will be ignored.
+     *
+     * @param node the node that will be the root level json object
+     * @param generator the json-p generator for writing the json
+     * @see <a href="https://javaee.github.io/jsonp/">json-p</a>
+     */
+    public void serialize(Node node, JsonGenerator generator) {
+        requireNonNull(node);
+        Log.info("Serializing Node to JSON.");
+        try {
+            serialize(null, node, generator);
+        } finally {
+            generator.close();
+        }
+    }
+
+    /**
+     * Recursive depth-first method that serializes nodes into json
+     *
+     * @param nodeName nullable String. If null, it is the root object, otherwise it is the property key for the object
+     * @param node the current node to be serialized
+     * @param generator the json-p generator for writing the json
+     */
+
+    private void serialize(String nodeName, Node node, JsonGenerator generator) {
+        requireNonNull(node);
+        BaseNodeMetaModel nodeMetaModel = JavaParserMetaModel.getNodeMetaModel(node.getClass()).orElseThrow(() -> new IllegalStateException("Unknown Node: " + node.getClass()));
+
+        if (nodeName == null) {
+            generator.writeStartObject();
+        } else {
+            generator.writeStartObject(nodeName);
+        }
+        generator.write(JsonNode.CLASS.propertyKey, node.getClass().getName());
+        this.writeNonMetaProperties(node, generator);
+        for (PropertyMetaModel propertyMetaModel : nodeMetaModel.getAllPropertyMetaModels()) {
+            String name = propertyMetaModel.getName();
+            Object value = propertyMetaModel.getValue(node);
+            if (value != null) {
+                if (propertyMetaModel.isNodeList()) {
+                    NodeList<Node> list = (NodeList<Node>) value;
+                    generator.writeStartArray(name);
+                    for (Node n : list) {
+                        serialize(null, n, generator);
+                    }
+                    generator.writeEnd();
+                } else if (propertyMetaModel.isNode()) {
+                    serialize(name, (Node) value, generator);
+                } else {
+                    generator.write(name, value.toString());
+                }
+            }
+        }
+        generator.writeEnd();
+    }
+
+    /***
+     * This method writes json for properties not included in meta model (i.e., RANGE and TOKEN_RANGE).
+     * This method could be overriden so that - for example - tokens are not written to json to save space
+     *
+     * @see com.github.javaparser.metamodel.BaseNodeMetaModel#getAllPropertyMetaModels()
+     */
+
+    protected void writeNonMetaProperties(Node node, JsonGenerator generator) {
+        this.writeRange(node, generator);
+        this.writeTokens(node, generator);
+    }
+
+    protected void writeRange(Node node, JsonGenerator generator) {
+        if (node.getRange().isPresent()) {
+            Range range = node.getRange().get();
+            generator.writeStartObject(JsonNode.RANGE.propertyKey);
+            generator.write(JsonRange.BEGIN_LINE.propertyKey, range.begin.line);
+            generator.write(JsonRange.BEGIN_COLUMN.propertyKey, range.begin.column);
+            generator.write(JsonRange.END_LINE.propertyKey, range.end.line);
+            generator.write(JsonRange.END_COLUMN.propertyKey, range.end.column);
+            generator.writeEnd();
+        }
+    }
+
+    protected void writeTokens(Node node, JsonGenerator generator) {
+        if (node.getTokenRange().isPresent()) {
+            TokenRange tokenRange = node.getTokenRange().get();
+            generator.writeStartObject(JsonNode.TOKEN_RANGE.propertyKey);
+            writeToken(JsonTokenRange.BEGIN_TOKEN.propertyKey, tokenRange.getBegin(), generator);
+            writeToken(JsonTokenRange.END_TOKEN.propertyKey, tokenRange.getEnd(), generator);
+            generator.writeEnd();
+        }
+    }
+
+    protected void writeToken(String name, JavaToken token, JsonGenerator generator) {
+        generator.writeStartObject(name);
+        generator.write(JsonToken.KIND.propertyKey, token.getKind());
+        generator.write(JsonToken.TEXT.propertyKey, token.getText());
+        generator.writeEnd();
+    }
+
+    /**
+     * excludes properties from meta model (except comment)
+     **/
+    public enum JsonNode {
+        RANGE("range"),
+        TOKEN_RANGE("tokenRange"),
+        COMMENT(decapitalize(JavaParserMetaModel.commentMetaModel.getTypeName())),
+        CLASS("!");
+        final String propertyKey;
+
+        JsonNode(String p) {
+            this.propertyKey = p;
+        }
+
+        public String toString() {
+            return this.propertyKey;
+        }
+    }
+
+    public enum JsonRange {
+        BEGIN_LINE("beginLine"),
+        BEGIN_COLUMN("beginColumn"),
+        END_LINE("endLine"),
+        END_COLUMN("endColumn");
+        final String propertyKey;
+
+        JsonRange(String p) {
+            this.propertyKey = p;
+        }
+
+        public String toString() {
+            return this.propertyKey;
+        }
+    }
+
+    public enum JsonTokenRange {
+        BEGIN_TOKEN("beginToken"),
+        END_TOKEN("endToken");
+        final String propertyKey;
+
+        JsonTokenRange(String p) {
+            this.propertyKey = p;
+        }
+
+        public String toString() {
+            return this.propertyKey;
+        }
+    }
+
+    public enum JsonToken {
+        TEXT("text"),
+        KIND("kind");
+        final String propertyKey;
+
+        JsonToken(String p) {
+            this.propertyKey = p;
+        }
+
+        public String toString() {
+            return this.propertyKey;
+        }
+    }
+}
diff --git a/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonDeserializerTest.java b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonDeserializerTest.java
new file mode 100644
index 0000000..4c7f000
--- /dev/null
+++ b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonDeserializerTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2018 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.serialization;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.comments.Comment;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.type.Type;
+import com.github.javaparser.javadoc.Javadoc;
+import com.github.javaparser.javadoc.JavadocBlockTag;
+import com.github.javaparser.resolution.SymbolResolver;
+import com.github.javaparser.resolution.types.ResolvedType;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Test;
+
+import javax.json.Json;
+import java.io.StringReader;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.serialization.JavaParserJsonSerializerTest.serialize;
+import static com.github.javaparser.utils.Utils.EOL;
+import static com.github.javaparser.utils.Utils.normalizeEolInTextBlock;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class JavaParserJsonDeserializerTest {
+    private final JavaParserJsonDeserializer deserializer = new JavaParserJsonDeserializer();
+
+    @Test
+    void simpleTest() {
+        CompilationUnit cu = parse("public class X{} class Z{}");
+        String serialized = serialize(cu, false);
+
+        Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+
+        assertEqualsNoEol("public class X {\n}\n\nclass Z {\n}\n", deserialized.toString());
+        assertEquals(cu.hashCode(), deserialized.hashCode());
+    }
+
+    @Test
+    void testRawType() {
+        Type type = parseType("Blub");
+        String serialized = serialize(type, false);
+
+        Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+
+        assertEqualsNoEol("Blub", deserialized.toString());
+        assertEquals(type.hashCode(), deserialized.hashCode());
+    }
+
+    @Test
+    void testDiamondType() {
+        Type type = parseType("Blub<>");
+        String serialized = serialize(type, false);
+
+        Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+
+        assertEqualsNoEol("Blub<>", deserialized.toString());
+        assertEquals(type.hashCode(), deserialized.hashCode());
+    }
+
+    @Test
+    void testGenerics() {
+        Type type = parseType("Blub<Blab, Bleb>");
+        String serialized = serialize(type, false);
+
+        Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+
+        assertEqualsNoEol("Blub<Blab, Bleb>", deserialized.toString());
+        assertEquals(type.hashCode(), deserialized.hashCode());
+    }
+
+    @Test
+    void testOperator() {
+        Expression expr = parseExpression("1+1");
+        String serialized = serialize(expr, false);
+
+        Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+
+        assertEqualsNoEol("1 + 1", deserialized.toString());
+        assertEquals(expr.hashCode(), deserialized.hashCode());
+    }
+
+    @Test
+    void testPrimitiveType() {
+        Type type = parseType("int");
+        String serialized = serialize(type, false);
+
+        Node deserialized = deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+
+        assertEqualsNoEol("int", deserialized.toString());
+        assertEquals(type.hashCode(), deserialized.hashCode());
+    }
+
+    @Test
+    void testComment() {
+        CompilationUnit cu = parse("/* block comment */\npublic class X{ \n // line comment\npublic void test() {}\n}");
+        String serialized = serialize(cu, false);
+
+        CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+        ClassOrInterfaceDeclaration classXDeclaration = deserialized.getClassByName("X").get();
+        assertTrue(classXDeclaration.getComment().isPresent());
+
+        Comment comment = classXDeclaration.getComment().get();
+        assertEquals("com.github.javaparser.ast.comments.BlockComment", comment.getClass().getName());
+        assertEquals(" block comment ", comment.getContent());
+
+        MethodDeclaration methodDeclaration = classXDeclaration.getMethods().get(0);
+        assertTrue(methodDeclaration.getComment().isPresent());
+        assertEquals("com.github.javaparser.ast.comments.LineComment", methodDeclaration.getComment().get().getClass().getName());
+        assertEquals(" line comment", methodDeclaration.getComment().get().getContent());
+    }
+
+    @Test
+    void testJavaDocComment() {
+        CompilationUnit cu = parse("public class X{ " +
+                "     /**\n" +
+                "     * Woke text.\n" +
+                "     * @param a blub\n" +
+                "     * @return true \n" +
+                "     */" +
+                "     public boolean test(int a) { return true; }\n" +
+                "}");
+        String serialized = serialize(cu, false);
+
+        CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+        ClassOrInterfaceDeclaration classDeclaration = deserialized.getClassByName("X").get();
+        MethodDeclaration methodDeclaration = classDeclaration.getMethods().get(0);
+        assertTrue(methodDeclaration.getJavadoc().isPresent());
+        Javadoc javadoc = methodDeclaration.getJavadoc().get();
+
+        JavadocBlockTag paramBlockTag = javadoc.getBlockTags().get(0);
+        assertEquals("param", paramBlockTag.getTagName());
+        assertEquals("blub", paramBlockTag.getContent().toText());
+
+        JavadocBlockTag returnBlockTag = javadoc.getBlockTags().get(1);
+        assertEquals("return", returnBlockTag.getTagName());
+        assertEquals("true", returnBlockTag.getContent().toText());
+    }
+
+    @Test
+    void testNonMetaProperties() {
+        CompilationUnit cu = parse("public class X{} class Z{}");
+        String serialized = serialize(cu, false);
+
+        CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+
+        assertTrue(deserialized.getRange().isPresent());
+        Range range = deserialized.getRange().get();
+        assertEquals(1, range.begin.line);
+        assertEquals(1, range.begin.line);
+        assertEquals(26, range.end.column);
+
+        assertTrue(deserialized.getTokenRange().isPresent());
+        TokenRange tokenRange = deserialized.getTokenRange().get();
+        assertEquals("public", tokenRange.getBegin().getText());
+        assertEquals("", tokenRange.getEnd().getText());
+    }
+
+    @Test
+    void testAttachingSymbolResolver() {
+        SymbolResolver stubResolver = new SymbolResolver() {
+            @Override
+            public <T> T resolveDeclaration(Node node, Class<T> resultClass) {
+                return null;
+            }
+
+            @Override
+            public <T> T toResolvedType(Type javaparserType, Class<T> resultClass) {
+                return null;
+            }
+
+            @Override
+            public ResolvedType calculateType(Expression expression) {
+                return null;
+            }
+        };
+        StaticJavaParser.getConfiguration().setSymbolResolver(stubResolver);
+        CompilationUnit cu = parse("public class X{} class Z{}");
+        String serialized = serialize(cu, false);
+
+        CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));
+        assertTrue(deserialized.containsData(Node.SYMBOL_RESOLVER_KEY));
+        assertEquals(stubResolver, deserialized.getData(Node.SYMBOL_RESOLVER_KEY));
+    }
+
+    @AfterAll
+    static void clearConfiguration() {
+        StaticJavaParser.setConfiguration(new ParserConfiguration());
+    }
+
+    /**
+     * Assert that "actual" equals "expected", and that any EOL characters in "actual" are correct for the platform.
+     */
+    private static void assertEqualsNoEol(String expected, String actual) {
+        assertEquals(normalizeEolInTextBlock(expected, EOL), actual);
+    }
+
+}
diff --git a/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonSerializerTest.java b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonSerializerTest.java
new file mode 100644
index 0000000..078a11c
--- /dev/null
+++ b/javaparser-core-serialization/src/test/java/com/github/javaparser/serialization/JavaParserJsonSerializerTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2018 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.serialization;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import org.junit.jupiter.api.Test;
+
+import javax.json.Json;
+import javax.json.stream.JsonGenerator;
+import javax.json.stream.JsonGeneratorFactory;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class JavaParserJsonSerializerTest {
+    @Test
+    void test() {
+        CompilationUnit cu = parse("class X{java.util.Y y;}");
+
+        String serialized = serialize(cu, false);
+
+        assertEquals("{\"!\":\"com.github.javaparser.ast.CompilationUnit\",\"range\":{\"beginLine\":1,\"beginColumn\":1,\"endLine\":1,\"endColumn\":23},\"tokenRange\":{\"beginToken\":{\"kind\":19,\"text\":\"class\"},\"endToken\":{\"kind\":0,\"text\":\"\"}},\"imports\":[],\"types\":[{\"!\":\"com.github.javaparser.ast.body.ClassOrInterfaceDeclaration\",\"range\":{\"beginLine\":1,\"beginColumn\":1,\"endLine\":1,\"endColumn\":23},\"tokenRange\":{\"beginToken\":{\"kind\":19,\"text\":\"class\"},\"endToken\":{\"kind\":95,\"text\":\"}\"}},\"extendedTypes\":[],\"implementedTypes\":[],\"isInterface\":\"false\",\"typeParameters\":[],\"members\":[{\"!\":\"com.github.javaparser.ast.body.FieldDeclaration\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":22},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":98,\"text\":\";\"}},\"modifiers\":[],\"variables\":[{\"!\":\"com.github.javaparser.ast.body.VariableDeclarator\",\"range\":{\"beginLine\":1,\"beginColumn\":21,\"endLine\":1,\"endColumn\":21},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"y\"},\"endToken\":{\"kind\":89,\"text\":\"y\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":21,\"endLine\":1,\"endColumn\":21},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"y\"},\"endToken\":{\"kind\":89,\"text\":\"y\"}},\"identifier\":\"y\"},\"type\":{\"!\":\"com.github.javaparser.ast.type.ClassOrInterfaceType\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":19},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"Y\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":19,\"endLine\":1,\"endColumn\":19},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"Y\"},\"endToken\":{\"kind\":89,\"text\":\"Y\"}},\"identifier\":\"Y\"},\"scope\":{\"!\":\"com.github.javaparser.ast.type.ClassOrInterfaceType\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":17},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"util\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":14,\"endLine\":1,\"endColumn\":17},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"util\"},\"endToken\":{\"kind\":89,\"text\":\"util\"}},\"identifier\":\"util\"},\"scope\":{\"!\":\"com.github.javaparser.ast.type.ClassOrInterfaceType\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":12},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"java\"}},\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":9,\"endLine\":1,\"endColumn\":12},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"java\"},\"endToken\":{\"kind\":89,\"text\":\"java\"}},\"identifier\":\"java\"},\"annotations\":[]},\"annotations\":[]},\"annotations\":[]}}],\"annotations\":[]}],\"modifiers\":[],\"name\":{\"!\":\"com.github.javaparser.ast.expr.SimpleName\",\"range\":{\"beginLine\":1,\"beginColumn\":7,\"endLine\":1,\"endColumn\":7},\"tokenRange\":{\"beginToken\":{\"kind\":89,\"text\":\"X\"},\"endToken\":{\"kind\":89,\"text\":\"X\"}},\"identifier\":\"X\"},\"annotations\":[]}]}", serialized);
+    }
+
+    static String serialize(Node node, boolean prettyPrint) {
+        Map<String, ?> config = new HashMap<>();
+        if (prettyPrint) {
+            config.put(JsonGenerator.PRETTY_PRINTING, null);
+        }
+        JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(config);
+        JavaParserJsonSerializer serializer = new JavaParserJsonSerializer();
+        StringWriter jsonWriter = new StringWriter();
+        try (JsonGenerator generator = generatorFactory.createGenerator(jsonWriter)) {
+            serializer.serialize(node, generator);
+        }
+        return jsonWriter.toString();
+    }
+}
diff --git a/javaparser-core-testing-bdd/pom.xml b/javaparser-core-testing-bdd/pom.xml
new file mode 100644
index 0000000..e6c4f87
--- /dev/null
+++ b/javaparser-core-testing-bdd/pom.xml
@@ -0,0 +1,108 @@
+<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.14.10-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>javaparser-core-testing-bdd</artifactId>
+    <description>The BDD test suite for javaparser-core</description>
+
+    <licenses>
+        <license>
+            <name>GNU Lesser General Public License</name>
+            <url>http://www.gnu.org/licenses/lgpl-3.0.html</url>
+            <distribution>repo</distribution>
+        </license>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+            <comments>A business-friendly OSS license</comments>
+        </license>
+    </licenses>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>jacoco-initialize</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>jacoco-site</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <encoding>UTF-8</encoding>
+                            <outputDirectory>${basedir}/target/classes</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>../javaparser-core/target/classes</directory>
+                                    <filtering>false</filtering>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <!-- no need to release this module -->
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>com.github.javaparser</groupId>
+            <artifactId>javaparser-core</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.vintage</groupId>
+            <artifactId>junit-vintage-engine</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jbehave</groupId>
+            <artifactId>jbehave-core</artifactId>
+            <version>4.5</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.github.valfirst</groupId>
+            <artifactId>jbehave-junit-runner</artifactId>
+            <version>2.3.0</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/BasicJBehaveTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/BasicJBehaveTest.java
new file mode 100644
index 0000000..267a294
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/BasicJBehaveTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.configuration.Configuration;
+import org.jbehave.core.configuration.MostUsefulConfiguration;
+import org.jbehave.core.failures.FailingUponPendingStep;
+import org.jbehave.core.io.LoadFromClasspath;
+import org.jbehave.core.io.StoryFinder;
+import org.jbehave.core.junit.JUnitStories;
+import org.jbehave.core.reporters.Format;
+import org.jbehave.core.reporters.StoryReporterBuilder;
+
+import java.util.List;
+
+import static org.jbehave.core.io.CodeLocations.codeLocationFromClass;
+
+abstract class BasicJBehaveTest extends JUnitStories {
+
+    private final String storiesPath;
+
+    BasicJBehaveTest(String storiesPath) {
+        this.storiesPath = storiesPath;
+        JUnitReportingRunner.recommendedControls(configuredEmbedder());
+    }
+
+    @Override
+    public final Configuration configuration() {
+        return new MostUsefulConfiguration()
+                // where to find the stories
+                .useStoryLoader(new LoadFromClasspath(this.getClass()))
+                // Fails if Steps are not implemented
+                .usePendingStepStrategy(new FailingUponPendingStep())
+                // CONSOLE and HTML reporting
+                .useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats()
+                        .withFormats(Format.CONSOLE, Format.HTML));
+    }
+
+    @Override
+    public final List<String> storyPaths() {
+        return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), storiesPath, "");
+    }
+
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/CommentParsingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/CommentParsingTest.java
new file mode 100644
index 0000000..df83e00
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/CommentParsingTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import com.github.javaparser.steps.CommentParsingSteps;
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.runner.RunWith;
+
+@RunWith(JUnitReportingRunner.class)
+public class CommentParsingTest extends BasicJBehaveTest {
+
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        return new InstanceStepsFactory(configuration(), new CommentParsingSteps());
+    }
+
+    public CommentParsingTest() {
+        super("**/comment*.story");
+    }
+}
+
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ComparingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ComparingTest.java
new file mode 100644
index 0000000..449e172
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ComparingTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import com.github.javaparser.steps.ComparingSteps;
+import com.github.javaparser.steps.SharedSteps;
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(JUnitReportingRunner.class)
+public class ComparingTest extends BasicJBehaveTest {
+
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        Map<String, Object> state = new HashMap<>();
+
+        return new InstanceStepsFactory(configuration(),
+                new SharedSteps(state),
+                new ComparingSteps());
+    }
+
+    public ComparingTest() {
+        super("**/comparing*.story");
+    }
+}
+
+
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ManipulationTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ManipulationTest.java
new file mode 100644
index 0000000..5206030
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ManipulationTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import com.github.javaparser.steps.ManipulationSteps;
+import com.github.javaparser.steps.SharedSteps;
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(JUnitReportingRunner.class)
+public class ManipulationTest extends BasicJBehaveTest {
+
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        Map<String, Object> state = new HashMap<>();
+
+        return new InstanceStepsFactory(configuration(),
+                new SharedSteps(state),
+                new ManipulationSteps(state));
+    }
+
+    public ManipulationTest() {
+        super("**/manipulation*.story");
+    }
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ParsingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ParsingTest.java
new file mode 100644
index 0000000..5381857
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/ParsingTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import com.github.javaparser.steps.ParsingSteps;
+import com.github.javaparser.steps.SharedSteps;
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(JUnitReportingRunner.class)
+public class ParsingTest extends BasicJBehaveTest {
+
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        Map<String, Object> state = new HashMap<>();
+
+        return new InstanceStepsFactory(configuration(),
+                new SharedSteps(state),
+                new ParsingSteps(state));
+    }
+
+    public ParsingTest() {
+        super("**/parsing*.story");
+    }
+}
+
+
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PositionRangeTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PositionRangeTest.java
new file mode 100644
index 0000000..f74c1e1
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PositionRangeTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import com.github.javaparser.steps.PositionRangeSteps;
+import com.github.javaparser.steps.SharedSteps;
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(JUnitReportingRunner.class)
+public class PositionRangeTest extends BasicJBehaveTest {
+
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        Map<String, Object> state = new HashMap<>();
+
+        return new InstanceStepsFactory(configuration(),
+                new SharedSteps(state),
+                new PositionRangeSteps());
+    }
+
+    public PositionRangeTest() {
+        super("**/position_range*.story");
+    }
+}
+
+
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PrettyPrintingTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PrettyPrintingTest.java
new file mode 100644
index 0000000..01d3561
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/PrettyPrintingTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import com.github.javaparser.steps.PrettyPrintingSteps;
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.runner.RunWith;
+
+@RunWith(JUnitReportingRunner.class)
+public class PrettyPrintingTest extends BasicJBehaveTest {
+
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        return new InstanceStepsFactory(configuration(), new PrettyPrintingSteps());
+    }
+
+    public PrettyPrintingTest() {
+        super("**/pretty_printing*.story");
+    }
+}
+
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/TestUtils.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/TestUtils.java
new file mode 100644
index 0000000..77a6fab
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/TestUtils.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import java.io.InputStream;
+
+public class TestUtils {
+
+    public static InputStream getSampleStream(String sampleName) {
+        InputStream is = TestUtils.class.getClassLoader().getResourceAsStream("com/github/javaparser/samples/"
+                + sampleName + ".java");
+        if (is == null) {
+            throw new RuntimeException("Example not found, check your test. Sample name: " + sampleName);
+        }
+        return is;
+    }
+
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/VisitorTest.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/VisitorTest.java
new file mode 100644
index 0000000..6695958
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/VisitorTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import com.github.javaparser.steps.SharedSteps;
+import com.github.javaparser.steps.VisitorSteps;
+import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
+import org.jbehave.core.steps.InjectableStepsFactory;
+import org.jbehave.core.steps.InstanceStepsFactory;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(JUnitReportingRunner.class)
+public class VisitorTest extends BasicJBehaveTest {
+
+    @Override
+    public InjectableStepsFactory stepsFactory() {
+        Map<String, Object> state = new HashMap<>();
+        return new InstanceStepsFactory(configuration(),
+                new SharedSteps(state),
+                new VisitorSteps(state));
+    }
+
+    public VisitorTest() {
+        super("**/visitor*.story");
+    }
+}
+
+
+
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/CommentParsingSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/CommentParsingSteps.java
new file mode 100644
index 0000000..d07990d
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/CommentParsingSteps.java
@@ -0,0 +1,432 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.comments.*;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.printer.PrettyPrinter;
+import com.github.javaparser.printer.PrettyPrinterConfiguration;
+import org.jbehave.core.annotations.Alias;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+import org.jbehave.core.model.ExamplesTable;
+import org.jbehave.core.steps.Parameters;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.Set;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+import static com.github.javaparser.Providers.*;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.Range.range;
+import static com.github.javaparser.steps.SharedSteps.getMemberByTypeAndPosition;
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class CommentParsingSteps {
+
+    private CompilationUnit compilationUnit;
+    private CommentsCollection commentsCollection;
+    private String sourceUnderTest;
+    private ParserConfiguration configuration = new ParserConfiguration();
+    private PrettyPrinter prettyPrinter = new PrettyPrinter(new PrettyPrinterConfiguration());
+
+    @Given("the class:$classSrc")
+    public void givenTheClass(String classSrc) {
+        this.sourceUnderTest = classSrc.trim();
+    }
+
+    @When("read sample \"$sampleName\" using encoding \"$encoding\"")
+    public void givenTheClassWithEncoding(String sampleName, String encoding) {
+        sourceUnderTest = null;
+        ParseResult<CompilationUnit> parseResult = new JavaParser(new ParserConfiguration()).parse(
+                COMPILATION_UNIT,
+                provider(
+                        TestUtils.getSampleStream(sampleName),
+                        Charset.forName(encoding)));
+        commentsCollection = parseResult.getCommentsCollection().orElse(new CommentsCollection());
+    }
+
+    @When("the class is parsed by the comment parser")
+    public void whenTheClassIsParsedByTheCommentParser() {
+        ParseResult<CompilationUnit> parseResult = new JavaParser(new ParserConfiguration()).parse(COMPILATION_UNIT, provider(sourceUnderTest));
+        commentsCollection = parseResult.getCommentsCollection().orElse(new CommentsCollection());
+    }
+
+    @When("the do not consider annotations as node start for code attribution is $value on the Java parser")
+    public void whenTheDoNotConsiderAnnotationsAsNodeStartForCodeAttributionIsTrueOnTheJavaParser(boolean value) {
+        configuration.setIgnoreAnnotationsWhenAttributingComments(value);
+    }
+
+    @When("the do not assign comments preceding empty lines is $value on the Java parser")
+    public void whenTheDoNotAssignCommentsPrecedingEmptyLinesIsTrueOnTheJavaParser(boolean value) {
+        configuration.setDoNotAssignCommentsPrecedingEmptyLines(value);
+    }
+
+    @When("the class is parsed by the Java parser")
+    public void whenTheClassIsParsedByTheJavaParser() {
+        ParseResult<CompilationUnit> result = new JavaParser(configuration).parse(COMPILATION_UNIT, provider(sourceUnderTest));
+        compilationUnit = result.getResult().get();
+    }
+
+    @Then("the Java parser cannot parse it because of an error")
+    public void javaParserCannotParseBecauseOfLexicalErrors() {
+        ParseResult<CompilationUnit> result = new JavaParser(configuration).parse(COMPILATION_UNIT, provider(sourceUnderTest));
+        if (result.isSuccessful()) {
+            fail("Lexical error expected");
+        }
+    }
+
+    @Then("the total number of comments is $expectedCount")
+    public void thenTheTotalNumberOfCommentsIs(int expectedCount) {
+        assertThat(commentsCollection.size(), is(expectedCount));
+    }
+
+    private <T extends Comment> T getCommentAt(Set<T> set, int index) {
+        Iterator<T> iterator = set.iterator();
+        T comment = null;
+        while (index >= 0) {
+            comment = iterator.next();
+            index--;
+        }
+        return comment;
+    }
+
+    @Then("line comment $position is \"$expectedContent\"")
+    public void thenLineCommentIs(int position, String expectedContent) {
+        LineComment lineCommentUnderTest = getCommentAt(commentsCollection.getLineComments(), position - 1);
+
+        assertThat(lineCommentUnderTest.getContent(), is(expectedContent));
+    }
+
+    @Then("block comment $position is \"$expectedContent\"")
+    public void thenBlockCommentIs(int position, String expectedContent) {
+        BlockComment lineCommentUnderTest = getCommentAt(commentsCollection.getBlockComments(), position - 1);
+
+        assertThat(lineCommentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("Javadoc comment $position is \"$expectedContent\"")
+    public void thenJavadocCommentIs(int position, String expectedContent) {
+        JavadocComment commentUnderTest = getCommentAt(commentsCollection.getJavadocComments(), position - 1);
+
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("the line comments have the following positions: $table")
+    public void thenTheLineCommentsHaveTheFollowingPositions(ExamplesTable examplesTable) {
+        int index = 0;
+        for (Parameters exampleRow : examplesTable.getRowsAsParameters()) {
+            Comment expectedLineComment = toComment(exampleRow, new LineComment());
+            Comment lineCommentUnderTest = getCommentAt(commentsCollection.getLineComments(), index);
+
+            Range underTestRange = lineCommentUnderTest.getRange().get();
+            Range expectedRange = expectedLineComment.getRange().get();
+
+            assertThat(underTestRange.begin.line, is(expectedRange.begin.line));
+            assertThat(underTestRange.begin.column, is(expectedRange.begin.column));
+            assertThat(underTestRange.end.line, is(expectedRange.end.line));
+            assertThat(underTestRange.end.column, is(expectedRange.end.column));
+            index++;
+        }
+    }
+
+    @Then("the block comments have the following positions: $table")
+    public void thenTheBlockCommentsHaveTheFollowingPositions(ExamplesTable examplesTable) {
+        int index = 0;
+        for (Parameters exampleRow : examplesTable.getRowsAsParameters()) {
+            Comment expectedLineComment = toComment(exampleRow, new BlockComment());
+            Comment lineCommentUnderTest = getCommentAt(commentsCollection.getBlockComments(), index);
+
+            Range underTestRange = lineCommentUnderTest.getRange().get();
+            Range expectedRange = expectedLineComment.getRange().get();
+
+            assertThat(underTestRange.begin.line, is(expectedRange.begin.line));
+            assertThat(underTestRange.begin.column, is(expectedRange.begin.column));
+            assertThat(underTestRange.end.line, is(expectedRange.end.line));
+            assertThat(underTestRange.end.column, is(expectedRange.end.column));
+            index++;
+        }
+    }
+
+    @Then("the Javadoc comments have the following positions: $table")
+    public void thenTheJavadocCommentsHaveTheFollowingPositions(ExamplesTable examplesTable) {
+        int index = 0;
+        for (Parameters exampleRow : examplesTable.getRowsAsParameters()) {
+            Comment expectedLineComment = toComment(exampleRow, new BlockComment());
+            Comment lineCommentUnderTest = getCommentAt(commentsCollection.getJavadocComments(), index);
+
+            Range underTestRange = lineCommentUnderTest.getRange().get();
+            Range expectedRange = expectedLineComment.getRange().get();
+
+            assertThat(underTestRange.begin.line, is(expectedRange.begin.line));
+            assertThat(underTestRange.begin.column, is(expectedRange.begin.column));
+            assertThat(underTestRange.end.line, is(expectedRange.end.line));
+            assertThat(underTestRange.end.column, is(expectedRange.end.column));
+            index++;
+        }
+    }
+
+    @Then("it is printed as:$src")
+    public void isPrintedAs(String src) {
+        assertThat(prettyPrinter.print(compilationUnit).trim(), is(src.trim()));
+    }
+
+    @Then("the compilation unit is not commented")
+    public void thenTheCompilationUnitIsNotCommented() {
+        assertEquals(false, compilationUnit.getComment().isPresent());
+    }
+
+    @Then("the compilation is commented \"$expectedContent\"")
+    public void thenTheCompilationIsCommentedCompilationUnitComment(String expectedContent) {
+        assertThat(compilationUnit.getComment().get().getContent(), is(expectedContent));
+    }
+
+    @Then("the compilation unit has $expectedCount contained comments")
+    public void thenTheCompilationUnitHasContainedComments(int expectedCount) {
+        assertThat(compilationUnit.getComments().size(), is(expectedCount));
+    }
+
+    @Then("the compilation unit has $expectedCount orphan comments")
+    public void thenTheCompilationUnitHasExpectedCountOrphanComments(int expectedCount) {
+        assertThat(compilationUnit.getOrphanComments().size(), is(expectedCount));
+    }
+
+    @Then("the compilation unit orphan comment $position is \"$expectedContent\"")
+    public void thenTheCompilationUnitOrphanCommentIs(int position, String expectedContent) {
+        Comment commentUnderTest = compilationUnit.getOrphanComments().get(position - 1);
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("comment $commentPosition in compilation unit is not an orphan")
+    public void thenCommentInCompilationUnitIsNotAnOrphan(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.isOrphan(), is(false));
+    }
+
+    @Then("comment $commentPosition in compilation unit is an orphan")
+    public void thenCommentInCompilationUnitIsAnOrphan(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.isOrphan(), is(true));
+    }
+
+    @Then("comment $commentPosition in compilation unit is \"$expectedContent\"")
+    public void thenCommentInCompilationUnitIs(int position, String expectedContent) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(position - 1);
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("class $position is not commented")
+    public void thenClassIsNotCommented(int position) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
+        assertEquals(false, classUnderTest.getComment().isPresent());
+    }
+
+    @Then("class $position is commented \"$expectedContent\"")
+    public void thenClassIsCommented(int position, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
+        assertThat(classUnderTest.getComment().get().getContent(), is(expectedContent));
+    }
+
+    @Then("class $position has $expectedCount total contained comments")
+    public void thenClassHasTotalContainedComments(int position, int expectedCount) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
+        assertThat(classUnderTest.getAllContainedComments().size(), is(expectedCount));
+    }
+
+    @Then("class $position has $expectedCount orphan comment")
+    @Alias("class $position has $expectedCount orphan comments")
+    public void thenClassHasOrphanComments(int position, int expectedCount) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
+        assertThat(classUnderTest.getOrphanComments().size(), is(expectedCount));
+    }
+
+    @Then("class $classPosition orphan comment $commentPosition is \"$expectedContent\"")
+    public void thenClassOrphanCommentIs(int classPosition, int commentPosition, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        Comment commentUnderTest = classUnderTest.getOrphanComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("method $methodPosition in class $classPosition is commented \"$expectedContent\"")
+    public void thenMethodInClassIsCommented(int methodPosition, int classPosition, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        assertThat(methodUnderTest.getComment().get().getContent(), equalToIgnoringWhiteSpace(expectedContent));
+    }
+
+    @Then("method $methodPosition in class $classPosition has $expectedCount total contained comments")
+    public void thenMethodInClassHasTotalContainedComments(int methodPosition, int classPosition, int expectedCount) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        assertThat(methodUnderTest.getAllContainedComments().size(), is(expectedCount));
+    }
+
+    @Then("comment $commentPosition in method $methodPosition in class $classPosition is \"$expectedContent\"")
+    public void thenCommentInMethodInClassIs(int commentPosition, int methodPosition, int classPosition, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        Comment commentUnderTest = methodUnderTest.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("method $methodPosition in class $classPosition has $expectedCount orphan comments")
+    public void thenMethodInClassHasOrphanComments(int methodPosition, int classPosition, int expectedCount) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        assertThat(methodUnderTest.getOrphanComments().size(), is(expectedCount));
+    }
+
+    @Then("block statement in method $methodPosition in class $classPosition has $expectedCount total contained comments")
+    public void thenBlockStatementInMethodInClassHasTotalContainedComments(int methodPosition, int classPosition, int expectedCount) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        BlockStmt blockStmtUnderTest = methodUnderTest.getBody().orElse(null);
+        assertThat(blockStmtUnderTest.getAllContainedComments().size(), is(expectedCount));
+    }
+
+    @Then("block statement in method $methodPosition in class $classPosition has $expectedCount orphan comments")
+    public void thenBlockStatementInMethodInClassHasOrphanComments(int methodPosition, int classPosition, int expectedCount) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        BlockStmt blockStmtUnderTest = methodUnderTest.getBody().orElse(null);
+        assertThat(blockStmtUnderTest.getOrphanComments().size(), is(expectedCount));
+    }
+
+    @Then("block statement in method $methodPosition in class $classPosition orphan comment $commentPosition is \"$expectedContent\"")
+    public void thenBlockStatementInMethodInClassIs(int methodPosition, int classPosition, int commentPosition, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        BlockStmt blockStmtUnderTest = methodUnderTest.getBody().orElse(null);
+        Comment commentUnderTest = blockStmtUnderTest.getOrphanComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("type of method $methodPosition in class $classPosition is commented \"$expectedContent\"")
+    public void thenTypeOfMethodInClassIsCommented(int methodPosition, int classPosition, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
+                MethodDeclaration.class);
+        Comment commentUnderTest = methodUnderTest.getType().getComment().get();
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("field $fieldPosition in class $classPosition contains $expectedCount comments")
+    public void thenFieldInClassContainsComments(int fieldPosition, int classPosition, int expectedCount) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
+                FieldDeclaration.class);
+        assertThat(fieldUnderTest.getAllContainedComments().size(), is(expectedCount));
+    }
+
+    @Then("field $fieldPosition in class $classPosition is not commented")
+    public void thenFieldInClassIsNotCommented(int fieldPosition, int classPosition) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
+                FieldDeclaration.class);
+        assertEquals(false, fieldUnderTest.getComment().isPresent());
+    }
+
+    @Then("field $fieldPosition in class $classPosition is commented \"$expectedContent\"")
+    public void thenFieldInClassIsCommented(int fieldPosition, int classPosition, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
+                FieldDeclaration.class);
+        Comment commentUnderTest = fieldUnderTest.getComment().get();
+        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
+    }
+
+    @Then("variable $variablePosition value of field $fieldPosition in class $classPosition is commented \"$expectedContent\"")
+    public void thenVariableValueOfFieldInClassIsCommented(int variablePosition, int fieldPosition, int classPosition, String expectedContent) {
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
+                FieldDeclaration.class);
+        VariableDeclarator variableUnderTest = fieldUnderTest.getVariable(variablePosition - 1);
+        Expression valueUnderTest = variableUnderTest.getInitializer().orElse(null);
+        Comment commentUnderTest = valueUnderTest.getComment().get();
+        assertThat(commentUnderTest.getContent(), is(expectedContent));
+    }
+
+    @Then("comment $commentPosition in compilation unit parent is ClassOrInterfaceDeclaration")
+    public void thenCommentInCompilationUnitParentIsClassOrInterfaceDeclaration(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getParentNode().get(), instanceOf(ClassOrInterfaceDeclaration.class));
+    }
+
+    @Then("comment $commentPosition in compilation unit commented node is ClassOrInterfaceDeclaration")
+    public void thenCommentInCompilationUnitCommentedNodeIsClassOrInterfaceDeclaration(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(ClassOrInterfaceDeclaration.class));
+    }
+
+    @Then("comment $commentPosition in compilation unit commented node is FieldDeclaration")
+    public void thenCommentInCompilationUnitCommentedNodeIsFieldDeclaration(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(FieldDeclaration.class));
+    }
+
+    @Then("comment $commentPosition in compilation unit commented node is IntegerLiteralExpr")
+    public void thenCommentInCompilationUnitCommentedNodeIsIntegerLiteralExpr(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(IntegerLiteralExpr.class));
+    }
+
+    @Then("comment $commentPosition in compilation unit commented node is ExpressionStmt")
+    public void thenCommentInCompilationUnitCommentedNodeIsIntegerExpressionStmt(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(ExpressionStmt.class));
+    }
+
+    @Then("comment $commentPosition in compilation unit commented node is PrimitiveType")
+    public void thenCommentInCompilationUnitCommentedNodeIsIntegerPrimitiveType(int commentPosition) {
+        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
+        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(PrimitiveType.class));
+    }
+
+    private Comment toComment(Parameters row, Comment comment) {
+        comment.setRange(range(Integer.parseInt(row.values().get("beginLine")),
+                Integer.parseInt(row.values().get("beginColumn")),
+                Integer.parseInt(row.values().get("endLine")),
+                Integer.parseInt(row.values().get("endColumn"))));
+        return comment;
+    }
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ComparingSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ComparingSteps.java
new file mode 100644
index 0000000..d10d259
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ComparingSteps.java
@@ -0,0 +1,61 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.ast.CompilationUnit;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class ComparingSteps {
+
+    private CompilationUnit first;
+    private CompilationUnit second;
+
+    /*
+     * Given steps
+     */
+
+    @Given("the first class:$classSrc")
+    public void givenTheFirstClass(String classSrc) {
+        this.first = parse(classSrc.trim());
+    }
+
+    @Given("the second class:$classSrc")
+    public void givenTheSecondClass(String classSrc) {
+        this.second = parse(classSrc.trim());
+    }
+
+    /*
+     * Then steps
+     */
+
+    @Then("they are equals")
+    public void thenTheyAreEquals() {
+        assertThat(first, is(equalTo(second)));
+    }
+
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ExistenceOfParentNodeVerifier.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ExistenceOfParentNodeVerifier.java
new file mode 100644
index 0000000..cb580f7
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ExistenceOfParentNodeVerifier.java
@@ -0,0 +1,542 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.HasParentNode;
+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.expr.*;
+import com.github.javaparser.ast.stmt.*;
+import com.github.javaparser.ast.type.*;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * The <code>ExistenceOfParentNodeVerifier</code> verifies that each node of the compilation unit has a parent set.
+ */
+class ExistenceOfParentNodeVerifier {
+
+    public void verify(CompilationUnit compilationUnit) throws AssertionError {
+        new Verifier().visit(compilationUnit, null);
+    }
+
+    private static class Verifier extends VoidVisitorAdapter<Void> {
+        private static void assertParentIsSet(HasParentNode<?> n) {
+            assertThat(n + " has no parent set!", n.getParentNode().orElse(null), is(notNullValue()));
+        }
+
+        @Override
+        public void visit(AnnotationDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(AnnotationMemberDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ArrayAccessExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ArrayCreationExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ArrayInitializerExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(AssertStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(AssignExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(BinaryExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(BlockComment n, Void arg) {
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(BlockStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(BooleanLiteralExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(BreakStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(CastExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(CatchClause n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(CharLiteralExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ClassExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ClassOrInterfaceDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ClassOrInterfaceType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(CompilationUnit n, Void arg) {
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ConditionalExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ConstructorDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ContinueStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(DoStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(DoubleLiteralExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(EmptyStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(EnclosedExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(EnumConstantDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(EnumDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ExplicitConstructorInvocationStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ExpressionStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(FieldAccessExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(FieldDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ForEachStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ForStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(IfStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(InitializerDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(InstanceOfExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(IntegerLiteralExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(JavadocComment n, Void arg) {
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(LabeledStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(LineComment n, Void arg) {
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(LambdaExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(LongLiteralExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(MarkerAnnotationExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(MemberValuePair n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(MethodCallExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(MethodDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(MethodReferenceExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(NameExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(NormalAnnotationExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(NullLiteralExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ObjectCreationExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(PackageDeclaration n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(Parameter n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(PrimitiveType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(Name n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(SimpleName n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ArrayType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ArrayCreationLevel n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(IntersectionType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(UnionType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ReturnStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(SingleMemberAnnotationExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(StringLiteralExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(SuperExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(SwitchEntry n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(SwitchStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(SynchronizedStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ThisExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(ThrowStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(TryStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(LocalClassDeclarationStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(TypeExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(NodeList n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(TypeParameter n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(UnaryExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(UnknownType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(VariableDeclarationExpr n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(VariableDeclarator n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(VoidType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(WhileStmt n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+
+        @Override
+        public void visit(WildcardType n, Void arg) {
+            assertParentIsSet(n);
+            super.visit(n, arg);
+        }
+    }
+
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ManipulationSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ManipulationSteps.java
new file mode 100644
index 0000000..ef59a36
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ManipulationSteps.java
@@ -0,0 +1,285 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.body.TypeDeclaration;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.stmt.TryStmt;
+import com.github.javaparser.ast.type.VoidType;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+import org.jbehave.core.annotations.Alias;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import java.util.Map;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static com.github.javaparser.ast.Modifier.staticModifier;
+import static com.github.javaparser.ast.NodeList.nodeList;
+import static com.github.javaparser.ast.type.PrimitiveType.intType;
+import static com.github.javaparser.steps.SharedSteps.getMethodByPositionAndClassPosition;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class ManipulationSteps {
+
+    /* Fields used to maintain step state within this step class */
+    private BlockStmt blockStmt;
+    private Statement statement;
+    private TryStmt tryStmt;
+    private NodeList<Expression> variableDeclarationExprList;
+    private ChangeMethodNameToUpperCaseVisitor changeMethodNameToUpperCaseVisitor;
+    private AddNewIntParameterCalledValueVisitor addNewIntParameterCalledValueVisitor;
+
+    /* Map that maintains shares state across step classes.  If manipulating the objects in the map you must update the state */
+    private Map<String, Object> state;
+
+    public ManipulationSteps(Map<String, Object> state) {
+        this.state = state;
+    }
+
+    @Given("a BlockStmt")
+    public void givenABlockStatement() {
+        blockStmt = new BlockStmt();
+    }
+
+    @Given("a Statement")
+    public void givenAStatement() {
+        statement = null;
+    }
+
+    @Given("a TryStmt")
+    public void givenATryStmt() {
+        tryStmt = new TryStmt();
+    }
+
+    @Given("a List of VariableDeclarations")
+    public void givenAListOfVariableDeclarations() {
+        variableDeclarationExprList = new NodeList<>();
+        variableDeclarationExprList.add(new VariableDeclarationExpr());
+        variableDeclarationExprList.add(new VariableDeclarationExpr());
+    }
+
+    @Given("a ChangeNameToUpperCaseVisitor")
+    public void givenAChangeNameToUpperCaseVisitor() {
+        changeMethodNameToUpperCaseVisitor = new ChangeMethodNameToUpperCaseVisitor();
+    }
+
+    @Given("a AddNewIntParameterCalledValueVisitor")
+    public void givenAAddNewParameterCalledValueVisitor() {
+        addNewIntParameterCalledValueVisitor = new AddNewIntParameterCalledValueVisitor();
+    }
+
+    @When("is the String \"$value\" is parsed by the JavaParser using parseBlock")
+    public void whenIsTheStringIsParsedByTheJavaParser(String value) {
+        blockStmt = parseBlock(value);
+    }
+
+    @When("is the String \"$value\" is parsed by the JavaParser using parseStatement")
+    public void whenIsTheStringIsParsedByTheJavaParserUsingParseStatement(String value) {
+        statement = parseStatement(value);
+    }
+
+    @When("the List of VariableDeclarations are set as the resources on TryStmt")
+    public void whenTheListOfVariableDeclarationsAreSetAsTheResourcesOnTryStmt() {
+        tryStmt.setResources(variableDeclarationExprList);
+    }
+
+    @When("empty list is set as the resources on TryStmt")
+    public void whenNullIsSetAsTheResourcesOnTryStmt() {
+        tryStmt.setResources(new NodeList<>());
+    }
+
+    @When("the package declaration is set to \"$packageName\"")
+    public void whenThePackageDeclarationIsSetTo(String packageName) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        compilationUnit.setPackageDeclaration(new PackageDeclaration(parseName(packageName)));
+        state.put("cu1", compilationUnit);
+    }
+
+    @When("a public class called \"$className\" is added to the CompilationUnit")
+    public void whenAClassCalledIsAddedToTheCompilationUnit(String className) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        TypeDeclaration<?> type = new ClassOrInterfaceDeclaration(createModifierList(PUBLIC), false, "CreateClass");
+        compilationUnit.setTypes(nodeList(type));
+        state.put("cu1", compilationUnit);
+    }
+
+    @When("a public static method called \"$methodName\" returning void is added to class $position in the compilation unit")
+    public void whenAStaticMethodCalledReturningIsAddedToClassInTheCompilationUnit(String methodName, int position) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        TypeDeclaration<?> type = compilationUnit.getType(position - 1);
+        NodeList<Modifier> modifiers = createModifierList(PUBLIC);
+        MethodDeclaration method = new MethodDeclaration(modifiers, new VoidType(), methodName);
+        modifiers.add(staticModifier());
+        method.setModifiers(modifiers);
+        type.addMember(method);
+        state.put("cu1", compilationUnit);
+    }
+
+    @When("$typeName varargs called \"$parameterName\" are added to method $methodPosition in class $classPosition")
+    public void whenVarargsCalledAreAddedToMethodInClass(String typeName, String parameterName, int methodPosition, int classPosition) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition)
+                .addAndGetParameter(typeName, parameterName)
+                .setVarArgs(true);
+    }
+
+    @When("a BlockStmt is added to method $methodPosition in class $classPosition")
+    public void whenABlockStmtIsAddedToMethodInClass(int methodPosition, int classPosition) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+        method.setBody(new BlockStmt());
+    }
+
+    @When("$className.$fieldName.$methodName(\"$stringValue\"); is added to the body of method $methodPosition in class $classPosition")
+    public void whenHelloWorldIsAddedToTheBodyOfMethodInClass(String className, String fieldName, String methodName, String stringValue,
+                                                              int methodPosition, int classPosition) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+        NameExpr clazz = new NameExpr(className);
+        FieldAccessExpr field = new FieldAccessExpr(clazz, fieldName);
+        MethodCallExpr call = new MethodCallExpr(field, methodName);
+        call.addArgument(new StringLiteralExpr(stringValue));
+        method.getBody().get().addStatement(call);
+    }
+
+    @When("method $methodPosition in class $classPosition has it's name converted to uppercase")
+    public void whenMethodInClassHasItsNameConvertedToUppercase(int methodPosition, int classPosition) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+        method.setName(method.getNameAsString().toUpperCase());
+    }
+
+    @When("method $methodPosition in class $classPosition has an int parameter called \"$paramName\" added")
+    public void whenMethodInClassHasAnIntArgumentCalledAdded(int methodPosition, int classPosition, String paramName) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+        method.addParameter(intType(), paramName);
+    }
+
+    @When("the compilation unit is cloned")
+    public void whenTheCompilationUnitIsCloned() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        state.put("cu1", compilationUnit.clone());
+    }
+
+    @When("the ChangeNameToUpperCaseVisitor visits to compilation unit")
+    public void whenTheVisitorVisitsToCompilationUnit() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        changeMethodNameToUpperCaseVisitor.visit(compilationUnit, null);
+        state.put("cu1", compilationUnit);
+    }
+
+    @When("the AddNewIntParameterCalledValueVisitor visits to compilation unit")
+    public void whenTheAddNewParameterCalledValueVisitorVisitsToCompilationUnit() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        addNewIntParameterCalledValueVisitor.visit(compilationUnit, null);
+        state.put("cu1", compilationUnit);
+    }
+
+    @Then("is not equal to null")
+    public void thenIsNotEqualToNull() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        assertNotEquals(compilationUnit, null);
+    }
+
+    @Then("is not equal to $value")
+    public void thenIsNotEqualTo(String value) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        assertNotEquals(compilationUnit, value);
+    }
+
+    @Then("Statement $position in BlockStmt toString is \"$expectedContent\"")
+    public void thenTheBlockStmtContentIs(int position, String expectedContent) {
+        Statement statementUnderTest = blockStmt.getStatement(position - 1);
+        assertThat(statementUnderTest.toString(), is(expectedContent));
+    }
+
+    @Then("Statement toString is \"$expectedContent\"")
+    public void thenStatementToStringIsxXy(String expectedContent) {
+        assertThat(statement.toString(), is(expectedContent));
+    }
+
+    @Then("all the VariableDeclarations parent is the TryStmt")
+    public void thenAllTheVariableDeclarationsParentIsTheTryStmt() {
+        variableDeclarationExprList.forEach(expr -> assertThat(expr.getParentNode().get(), is(tryStmt)));
+    }
+
+    @Then("the TryStmt has no child nodes")
+    public void thenTheTryStmtHasNotChildNodes() {
+        assertThat(tryStmt.getChildNodes().size(), is(0));
+    }
+
+    @Then("method $methodPosition in class $classPosition has the name \"$expectedName\"")
+    public void thenMethodInClassHasTheName(int methodPosition, int classPosition, String expectedName) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+        assertThat(method.getNameAsString(), is(expectedName));
+    }
+
+    @Then("method $methodPosition in class $classPosition has $expectedCount parameters")
+    @Alias("method $methodPosition in class $classPosition has $expectedCount parameter")
+    public void thenMethodInClassHasArguments(int methodPosition, int classPosition, int expectedCount) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+
+        assertThat(method.getParameters().size(), is(expectedCount));
+    }
+
+    @Then("method $methodPosition in class $classPosition parameter $parameterPosition is type int called \"$expectedName\"")
+    public void thenMethodInClassParameterIsTypeIntCalled(int methodPosition, int classPosition, int parameterPosition, String expectedName) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+        Parameter parameter = method.getParameter(parameterPosition - 1);
+        assertThat(parameter.getType(), is(intType()));
+        assertThat(parameter.getNameAsString(), is(expectedName));
+    }
+
+    private static class ChangeMethodNameToUpperCaseVisitor extends VoidVisitorAdapter<Void> {
+        @Override
+        public void visit(MethodDeclaration n, Void arg) {
+            n.setName(n.getNameAsString().toUpperCase());
+        }
+    }
+
+    private static class AddNewIntParameterCalledValueVisitor extends VoidVisitorAdapter<Void> {
+        @Override
+        public void visit(MethodDeclaration n, Void arg) {
+            n.addParameter(intType(), "value");
+        }
+    }
+}
+
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ParsingSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ParsingSteps.java
new file mode 100644
index 0000000..2112aab
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/ParsingSteps.java
@@ -0,0 +1,344 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+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.expr.*;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import java.util.List;
+import java.util.Map;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.steps.SharedSteps.getMemberByTypeAndPosition;
+import static com.github.javaparser.steps.SharedSteps.getMethodByPositionAndClassPosition;
+import static java.lang.String.format;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class ParsingSteps {
+
+    private Map<String, Object> state;
+
+    public ParsingSteps(Map<String, Object> state) {
+        this.state = state;
+    }
+
+    private String sourceUnderTest;
+
+    /*
+     * Given steps
+     */
+
+    @Given("the class:$classSrc")
+    public void givenTheClass(String classSrc) {
+        this.sourceUnderTest = classSrc.trim();
+    }
+
+
+    /*
+     * When steps
+     */
+
+    @When("I take the ArrayCreationExpr")
+    public void iTakeTheArrayCreationExpr() {
+        setSelectedNodeFromCompilationUnit(ArrayCreationExpr.class);
+    }
+
+    @When("I take the PackageDeclaration")
+    public void iTakeThePackageDeclaration() {
+        setSelectedNodeFromCompilationUnit(PackageDeclaration.class);
+    }
+
+    @When("I take the ObjectCreationExpr")
+    public void iTakeTheObjectCreationExpr() throws ClassNotFoundException {
+        setSelectedNodeFromCompilationUnit(ObjectCreationExpr.class);
+    }
+
+    /*
+     * Then steps
+     */
+
+    @Then("constructor $constructorPosition in class $classPosition declaration as a String is \"$expectedString\"")
+    public void thenTheConstructorDeclarationAsAStringIs(int constructorPosition, int classPosition, String expectedString) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
+        ConstructorDeclaration constructor = (ConstructorDeclaration) clazz.getMember(constructorPosition - 1);
+        assertThat(constructor.getDeclarationAsString(), is(expectedString));
+    }
+
+    @Then("constructor $constructorPosition in class $classPosition declaration short form as a String is \"$expectedString\"")
+    public void thenConstructorInClassDeclarationShortFormAsAStringIs(int constructorPosition, int classPosition, String expectedString) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
+        ConstructorDeclaration constructor = (ConstructorDeclaration) clazz.getMember(constructorPosition - 1);
+        assertThat(constructor.getDeclarationAsString(false, false), is(expectedString));
+    }
+
+    @Then("method $methodPosition in class $classPosition declaration as a String is \"$expectedString\"")
+    public void thenMethod1InClass1DeclarationAsAStringIs(int methodPosition, int classPosition, String expectedString) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
+        MethodDeclaration method = (MethodDeclaration) clazz.getMember(methodPosition - 1);
+        assertThat(method.getDeclarationAsString(), is(expectedString));
+    }
+
+    @Then("method $methodPosition in class $classPosition declaration as a String short form is \"$expectedString\"")
+    public void thenMethodInClassDeclarationAsAStringShortFormIs(int methodPosition, int classPosition, String expectedString) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
+        MethodDeclaration method = (MethodDeclaration) clazz.getMember(methodPosition - 1);
+        assertThat(method.getDeclarationAsString(false, false), is(expectedString));
+    }
+
+    @Then("field $fieldPosition in class $classPosition contains annotation $annotationPosition value is \"$expectedValue\"")
+    public void thenFieldInClassContainsAnnotationValueIs(int fieldPosition, int classPosition, int annotationPosition, String expectedValue) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+
+        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
+        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
+                FieldDeclaration.class);
+        AnnotationExpr annotationUnderTest = fieldUnderTest.getAnnotation(annotationPosition - 1);
+        assertThat(annotationUnderTest.getChildNodes().get(1).toString(), is(expectedValue));
+    }
+
+    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition is called $expectedName")
+    public void thenLambdaInClassIsCalled(int statementPosition, int methodPosition, int classPosition, String expectedName) {
+        Statement statement = getStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        VariableDeclarationExpr expression = (VariableDeclarationExpr) ((ExpressionStmt) statement).getExpression();
+        VariableDeclarator variableDeclarator = expression.getVariable(0);
+        assertThat(variableDeclarator.getNameAsString(), is(expectedName));
+    }
+
+    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition body is \"$expectedBody\"")
+    public void thenLambdaInStatementInMethodInClassBody(int statementPosition, int methodPosition, int classPosition,
+                                                         String expectedBody) {
+        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        assertThat(lambdaExpr.getBody().toString(), is(expectedBody));
+    }
+
+    @Then("lambda in method call in statement $statementPosition in method $methodPosition in class $classPosition body is \"$expectedBody\"")
+    public void thenLambdaInMethodCallInStatementInMethodInClassBody(int statementPosition, int methodPosition, int classPosition,
+                                                                     String expectedBody) {
+        ExpressionStmt statement = getStatementInMethodInClass(statementPosition, methodPosition, classPosition).asExpressionStmt();
+        VariableDeclarationExpr variableDeclarationExpr = statement.getExpression().asVariableDeclarationExpr();
+        VariableDeclarator variableDeclarator = variableDeclarationExpr.getVariable(0);
+        MethodCallExpr methodCallExpr = (MethodCallExpr) variableDeclarator.getInitializer().orElse(null);
+        CastExpr castExpr = methodCallExpr.getArgument(0).asCastExpr();
+        LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
+        assertThat(lambdaExpr.getBody().toString(), is(expectedBody));
+    }
+
+    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition block statement is null")
+    public void thenLambdaInStatementInMethodInClassBlockStatementIsNull(int statementPosition, int methodPosition, int classPosition) {
+        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        BlockStmt blockStmt = lambdaExpr.getBody().asBlockStmt();
+        assertEquals(true, blockStmt.getStatements().isEmpty());
+    }
+
+    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition has parameters with non-null type")
+    public void thenLambdaInStatementInMethodInClassHasParametersWithNonNullType(int statementPosition, int methodPosition, int classPosition) {
+        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        for (Parameter parameter : lambdaExpr.getParameters()) {
+            assertThat(parameter.getType(), is(notNullValue()));
+        }
+    }
+
+    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition block statement is \"$expectedBody\"")
+    public void thenLambdaInStatementInMethodInClassBlockStatement(int statementPosition, int methodPosition, int classPosition,
+                                                                   String expectedBody) {
+        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        BlockStmt blockStmt = lambdaExpr.getBody().asBlockStmt();
+        Statement lambdaStmt = blockStmt.getStatement(0);
+        assertThat(lambdaStmt.toString(), is(expectedBody));
+    }
+
+    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition is parent of contained body")
+    public void thenLambdaInStatementInMethodInClassIsParentOfContainedBody(int statementPosition, int methodPosition, int classPosition) {
+        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        Statement body = lambdaExpr.getBody();
+        assertThat(body.getParentNode().get(), is(lambdaExpr));
+    }
+
+    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition is parent of contained parameter")
+    public void thenLambdaInStatementInMethodInClassIsParentOfContainedParameter(int statementPosition, int methodPosition, int classPosition) {
+        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        Parameter parameter = lambdaExpr.getParameter(0);
+        assertThat(parameter.getParentNode().get(), is(lambdaExpr));
+    }
+
+    @Then("method reference in statement $statementPosition in method $methodPosition in class $classPosition scope is $expectedName")
+    public void thenMethodReferenceInStatementInMethodInClassIsScope(int statementPosition, int methodPosition,
+                                                                     int classPosition, String expectedName) {
+        ExpressionStmt statementUnderTest = getStatementInMethodInClass(statementPosition, methodPosition, classPosition).asExpressionStmt();
+        assertEquals(1, statementUnderTest.findAll(MethodReferenceExpr.class).size());
+        MethodReferenceExpr methodReferenceUnderTest = statementUnderTest.findFirst(MethodReferenceExpr.class).get();
+        assertThat(methodReferenceUnderTest.getScope().toString(), is(expectedName));
+    }
+
+    @Then("method reference in statement $statementPosition in method $methodPosition in class $classPosition identifier is $expectedName")
+    public void thenMethodReferenceInStatementInMethodInClassIdentifierIsCompareByAge(int statementPosition, int methodPosition,
+                                                                                      int classPosition, String expectedName) {
+        Statement statementUnderTest = getStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        assertEquals(1, statementUnderTest.findAll(MethodReferenceExpr.class).size());
+        MethodReferenceExpr methodReferenceUnderTest = statementUnderTest.findFirst(MethodReferenceExpr.class).get();
+        assertThat(methodReferenceUnderTest.getIdentifier(), is(expectedName));
+    }
+
+    @Then("method $methodPosition class $classPosition is a default method")
+    public void thenMethodClassIsADefaultMethod(int methodPosition, int classPosition) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration methodUnderTest = getMethodByPositionAndClassPosition(compilationUnit,
+                methodPosition, classPosition);
+        assertThat(methodUnderTest.isDefault(), is(true));
+    }
+
+    @Then("method $methodPosition class $classPosition is not a default method")
+    public void thenMethodClassIsNotADefaultMethod(int methodPosition, int classPosition) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration methodUnderTest = getMethodByPositionAndClassPosition(compilationUnit,
+                methodPosition, classPosition);
+        assertThat(methodUnderTest.isDefault(), is(false));
+    }
+
+    private Statement getStatementInMethodInClass(int statementPosition, int methodPosition, int classPosition) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
+        return method.getBody().get().getStatement(statementPosition - 1);
+    }
+
+    private LambdaExpr getLambdaExprInStatementInMethodInClass(int statementPosition, int methodPosition, int classPosition) {
+        Statement statement = getStatementInMethodInClass(statementPosition, methodPosition, classPosition);
+        VariableDeclarationExpr expression = ((ExpressionStmt) statement).getExpression().asVariableDeclarationExpr();
+        VariableDeclarator variableDeclarator = expression.getVariable(0);
+        return (LambdaExpr) variableDeclarator.getInitializer().orElse(null);
+    }
+
+    @Then("all nodes refer to their parent")
+    public void allNodesReferToTheirParent() {
+        assertAllNodesOfTheCompilationUnitHaveTheirParentSet("cu1");
+    }
+
+    @Then("all nodes of the second compilation unit refer to their parent")
+    public void thenAllNodesOfTheSecondCompilationUnitReferToTheirParent() {
+        assertAllNodesOfTheCompilationUnitHaveTheirParentSet("cu2");
+    }
+
+    private void assertAllNodesOfTheCompilationUnitHaveTheirParentSet(String stateKey) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get(stateKey);
+        ExistenceOfParentNodeVerifier parentVerifier = new ExistenceOfParentNodeVerifier();
+        parentVerifier.verify(compilationUnit);
+    }
+
+    @Then("ThenExpr in the conditional expression of the statement $statementPosition in method $methodPosition in class $classPosition is LambdaExpr")
+    public void thenLambdaInConditionalExpressionInMethodInClassIsParentOfContainedParameter(int statementPosition, int methodPosition, int classPosition) {
+        ReturnStmt returnStmt = getStatementInMethodInClass(statementPosition, methodPosition, classPosition).asReturnStmt();
+        ConditionalExpr conditionalExpr = (ConditionalExpr) returnStmt.getExpression().orElse(null);
+        assertThat(conditionalExpr.getElseExpr().getClass().getName(), is(LambdaExpr.class.getName()));
+    }
+
+    @Then("the begin line is $line")
+    public void thenTheBeginLineIs(int line) {
+        Node node = (Node) state.get("selectedNode");
+        assertEquals(line, node.getBegin().get().line);
+    }
+
+    @Then("the begin column is $column")
+    public void thenTheBeginColumnIs(int column) {
+        Node node = (Node) state.get("selectedNode");
+        assertEquals(column, node.getBegin().get().column);
+    }
+
+    @Then("the end line is $line")
+    public void thenTheEndLineIs(int line) {
+        Node node = (Node) state.get("selectedNode");
+        assertEquals(line, node.getEnd().get().line);
+    }
+
+    @Then("the end column is $column")
+    public void thenTheEndColumnIs(int column) {
+        Node node = (Node) state.get("selectedNode");
+        assertEquals(column, node.getEnd().get().column);
+    }
+
+    @Then("no errors are reported")
+    public void thenNoErrorsAreReported() {
+        // this is present just for readability in the scenario specification
+        // if the code is not parsed then exceptions are thrown before reaching this step
+    }
+
+    @Then("the package name is $package")
+    public void thenThePackageNameIs(String expected) {
+        PackageDeclaration node = (PackageDeclaration) state.get("selectedNode");
+        assertEquals(expected, node.getNameAsString());
+        assertEquals(expected, node.getName().toString());
+    }
+
+    @Then("the type's diamond operator flag should be $expectedValue")
+    public void thenTheUsesDiamondOperatorShouldBeBooleanAsString(boolean expectedValue) {
+        ObjectCreationExpr expr = (ObjectCreationExpr) state.get("selectedNode");
+        assertEquals(expectedValue, expr.getType().isUsingDiamondOperator());
+    }
+
+    @Then("the Java parser cannot parse it because of an error")
+    public void javaParserCannotParseBecauseOfLexicalErrors() {
+        ParseResult<CompilationUnit> result = new JavaParser().parse(COMPILATION_UNIT, provider(sourceUnderTest));
+        if (result.isSuccessful()) {
+            fail("Lexical error expected");
+        }
+    }
+
+    @Then("the assignExpr produced doesn't have a null target")
+    public void thenTheAssignExprProducedDoesntHaveANullTarget() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        ClassOrInterfaceDeclaration classDeclaration = compilationUnit.getType(0).asClassOrInterfaceDeclaration();
+        ConstructorDeclaration ctor = classDeclaration.getMember(1).asConstructorDeclaration();
+        ExpressionStmt assignStmt = ctor.getBody().getStatement(0).asExpressionStmt();
+        AssignExpr assignExpr = assignStmt.getExpression().asAssignExpr();
+        assertNotNull(assignExpr.getTarget());
+        assertEquals(NameExpr.class, assignExpr.getTarget().getClass());
+        assertEquals(assignExpr.getTarget().asNameExpr().getNameAsString(), "mString");
+    }
+
+    private void setSelectedNodeFromCompilationUnit(Class<? extends Node> nodeType) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        List<? extends Node> nodes = compilationUnit.findAll(nodeType);
+        if (nodes.size() != 1) {
+            throw new RuntimeException(format("Exactly one %s expected", nodeType.getSimpleName()));
+        }
+        state.put("selectedNode", nodes.get(0));
+    }
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/PositionRangeSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/PositionRangeSteps.java
new file mode 100644
index 0000000..bb203e5
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/PositionRangeSteps.java
@@ -0,0 +1,129 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.Position;
+import com.github.javaparser.Range;
+import org.jbehave.core.annotations.BeforeScenario;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import static com.github.javaparser.Position.pos;
+import static com.github.javaparser.Range.range;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PositionRangeSteps {
+
+    private Position position;
+    private Position secondPosition;
+    private Range range;
+    private Range secondRange;
+
+    @BeforeScenario
+    public void reset() {
+        position = null;
+        secondPosition = null;
+        range = null;
+        secondRange = null;
+    }
+    /*
+	 * Given steps
+     */
+
+    @Given("the position $line, $column")
+    public void givenThePosition(int line, int column) {
+        this.position = pos(line, column);
+    }
+
+    @Given("the range $line1, $column1 - $line2, $column2")
+    public void givenTheRange(int line1, int column1, int line2, int column2) {
+        this.range = range(line1, column1, line2, column2);
+    }
+
+    /*
+	 * When steps
+     */
+
+    @When("I compare to position $line, $column")
+    public void iCompareToPosition(int line, int column) {
+        secondPosition = pos(line, column);
+    }
+
+    @When("I compare to range $line1, $column1 - $line2, $column2")
+    public void whenICompareToRange(int line1, int column1, int line2, int column2) {
+        this.secondRange = range(line1, column1, line2, column2);
+    }
+
+    /*
+	 * Then steps
+     */
+
+    @Then("the positions are equal")
+    public void thenThePositionsAreEqual() {
+        assertTrue(position.equals(secondPosition));
+    }
+
+    @Then("it is after the {first|} position")
+    public void thenItIsAfterTheFirstPosition() {
+        if (secondPosition != null) {
+            assertTrue(secondPosition.isAfter(position));
+        } else {
+            assertTrue(secondRange.isAfter(position));
+        }
+    }
+
+    @Then("it is before the {first|} position")
+    public void thenItIsBeforeTheFirstPosition() {
+        if (secondPosition != null) {
+            assertTrue(secondPosition.isBefore(position));
+        } else {
+            assertTrue(secondRange.isBefore(position));
+        }
+    }
+
+    @Then("the positions are not equal")
+    public void thenThePositionsAreNotEqual() {
+        assertFalse(position.equals(secondPosition));
+    }
+
+    @Then("it is not after the {first|} position")
+    public void thenItIsNotAfterTheFirstPosition() {
+        assertFalse(secondPosition.isAfter(position));
+    }
+
+    @Then("it is not before the {first|} position")
+    public void thenItIsNotBeforeTheFirstPosition() {
+        assertFalse(secondPosition.isBefore(position));
+    }
+
+    @Then("the ranges are equal")
+    public void theRangesAreEqual() {
+        assertTrue(range.equals(secondRange));
+    }
+
+    @Then("it is contained in the first range")
+    public void itIsContainedInTheFirstRange() {
+        assertTrue(range.contains(secondRange));
+    }
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/PrettyPrintingSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/PrettyPrintingSteps.java
new file mode 100644
index 0000000..60c1af4
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/PrettyPrintingSteps.java
@@ -0,0 +1,112 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.visitor.ModifierVisitor;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.utils.Utils.readerToString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PrettyPrintingSteps {
+
+    private Node resultNode;
+    private String sourceUnderTest;
+
+    @Given("the {class|compilation unit|expression|block|statement|import|annotation|body|class body|interface body}:$classSrc")
+    public void givenTheClass(String classSrc) {
+        this.sourceUnderTest = classSrc.trim();
+    }
+
+    @Given("the {class|compilation unit|expression|block|statement|import|annotation|body|class body|interface body} in the file \"$classFile\"")
+    public void givenTheClassInTheFile(String classFile) throws URISyntaxException, IOException {
+        URL url = getClass().getResource("../samples/" + classFile);
+        sourceUnderTest = readerToString(new FileReader(new File(url.toURI()))).trim();
+    }
+
+    @When("the {class|compilation unit} is parsed by the Java parser")
+    public void whenTheClassIsParsedByTheJavaParser() {
+        resultNode = parse(sourceUnderTest);
+    }
+
+    @When("the expression is parsed by the Java parser")
+    public void whenTheExpressionIsParsedByTheJavaParser() {
+        resultNode = parseExpression(sourceUnderTest);
+    }
+
+    @When("the block is parsed by the Java parser")
+    public void whenTheBlockIsParsedByTheJavaParser() {
+        resultNode = parseBlock(sourceUnderTest);
+    }
+
+    @When("the statement is parsed by the Java parser")
+    public void whenTheStatementIsParsedByTheJavaParser() {
+        resultNode = parseStatement(sourceUnderTest);
+    }
+
+    @When("the import is parsed by the Java parser")
+    public void whenTheImportIsParsedByTheJavaParser() {
+        resultNode = parseImport(sourceUnderTest);
+    }
+
+    @When("the annotation is parsed by the Java parser")
+    public void whenTheAnnotationIsParsedByTheJavaParser() {
+        resultNode = parseAnnotation(sourceUnderTest);
+    }
+
+    @When("the annotation body declaration is parsed by the Java parser")
+    public void whenTheBodyDeclarationIsParsedByTheJavaParser() {
+        resultNode = parseAnnotationBodyDeclaration(sourceUnderTest);
+    }
+
+    @When("the class body declaration is parsed by the Java parser")
+    public void whenTheClassBodyDeclarationIsParsedByTheJavaParser() {
+        resultNode = parseBodyDeclaration(sourceUnderTest);
+    }
+
+    @When("the interface body declaration is parsed by the Java parser")
+    public void whenTheInterfaceBodyDeclarationIsParsedByTheJavaParser() {
+        resultNode = parseBodyDeclaration(sourceUnderTest);
+    }
+
+    @When("the class is visited by an empty ModifierVisitorAdapter")
+    public void whenTheClassIsVisitedByAnEmptyModifierVisitorAdapter() {
+        (new ModifierVisitor<Void>() {
+        }).visit((CompilationUnit) resultNode, null);
+    }
+
+    @Then("it is printed as:$src")
+    public void isPrintedAs(String src) {
+        assertEquals(src.trim(), resultNode.toString().trim());
+    }
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/SharedSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/SharedSteps.java
new file mode 100644
index 0000000..5aeda68
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/SharedSteps.java
@@ -0,0 +1,163 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.TypeDeclaration;
+import org.hamcrest.CoreMatchers;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Map;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class SharedSteps {
+
+    /* Map that maintains shares state across step classes.  If manipulating the objects in the map you must update the state */
+    private Map<String, Object> state;
+
+    public SharedSteps(Map<String, Object> state) {
+        this.state = state;
+    }
+
+    /*
+     * Given steps
+     */
+
+    @Given("a CompilationUnit")
+    public void givenACompilationUnit() {
+        state.put("cu1", new CompilationUnit());
+    }
+
+    @Given("a second CompilationUnit")
+    public void givenASecondCompilationUnit() {
+        state.put("cu2", new CompilationUnit());
+    }
+
+    /*
+     * When steps
+     */
+
+    @When("the following source is parsed:$classSrc")
+    public void whenTheFollowingSourceIsParsed(String classSrc) {
+        state.put("cu1", parse(classSrc.trim()));
+    }
+
+    @When("the following source is parsed (trimming space):$classSrc")
+    public void whenTheFollowingSourceIsParsedTrimmingSpace(String classSrc) {
+        state.put("cu1", parse(classSrc.trim()));
+    }
+
+    @When("the following sources is parsed by the second CompilationUnit:$classSrc")
+    public void whenTheFollowingSourcesIsParsedBytTheSecondCompilationUnit(String classSrc) {
+        state.put("cu2", parse(classSrc.trim()));
+    }
+
+    @When("file \"$fileName\" is parsed")
+    public void whenTheJavaFileIsParsed(String fileName) throws IOException, URISyntaxException {
+        URL url = getClass().getResource("../samples/" + fileName);
+        CompilationUnit compilationUnit = parse(new File(url.toURI()));
+        state.put("cu1", compilationUnit);
+    }
+
+    @Then("the CompilationUnit is equal to the second CompilationUnit")
+    public void thenTheCompilationUnitIsEqualToTheSecondCompilationUnit() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
+
+        assertThat(compilationUnit, is(equalTo(compilationUnit2)));
+    }
+
+    @Then("the CompilationUnit has the same hashcode to the second CompilationUnit")
+    public void thenTheCompilationUnitHasTheSameHashcodeToTheSecondCompilationUnit() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
+
+        assertThat(compilationUnit.hashCode(), is(equalTo(compilationUnit2.hashCode())));
+    }
+
+    @Then("the CompilationUnit is not equal to the second CompilationUnit")
+    public void thenTheCompilationUnitIsNotEqualToTheSecondCompilationUnit() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
+
+        assertThat(compilationUnit, not(equalTo(compilationUnit2)));
+    }
+
+    @Then("the CompilationUnit has a different hashcode to the second CompilationUnit")
+    public void thenTheCompilationUnitHasADifferentHashcodeToTheSecondCompilationUnit() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
+
+        assertThat(compilationUnit.hashCode(), not(equalTo(compilationUnit2.hashCode())));
+    }
+
+    @Then("the expected source should be:$classSrc")
+    public void thenTheExpectedSourcesShouldBe(String classSrc) {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        assertThat(compilationUnit.toString(), CoreMatchers.is(equalToIgnoringWhiteSpace(classSrc)));
+    }
+
+    public static <T extends BodyDeclaration<?>> T getMemberByTypeAndPosition(TypeDeclaration<?> typeDeclaration, int position, Class<T> typeClass) {
+        int typeCount = 0;
+        for (BodyDeclaration<?> declaration : typeDeclaration.getMembers()) {
+            if (declaration.getClass().equals(typeClass)) {
+                if (typeCount == position) {
+                    return (T) declaration;
+                }
+                typeCount++;
+            }
+        }
+        throw new IllegalArgumentException("No member " + typeClass + " at position: " + position);
+    }
+
+    public static MethodDeclaration getMethodByPositionAndClassPosition(CompilationUnit compilationUnit,
+                                                                        int methodPosition, int classPosition) {
+        TypeDeclaration<?> type = compilationUnit.getType(classPosition - 1);
+
+        int memberCount = 0;
+        int methodCount = 0;
+        for (BodyDeclaration<?> bodyDeclaration : type.getMembers()) {
+            if (bodyDeclaration instanceof MethodDeclaration) {
+                if (methodCount == methodPosition - 1) {
+                    return (MethodDeclaration) type.getMember(memberCount);
+                }
+                methodCount++;
+            }
+            memberCount++;
+        }
+        throw new IllegalArgumentException("Method not found at position " + methodPosition + "in class " + classPosition);
+    }
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/VisitorSteps.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/VisitorSteps.java
new file mode 100644
index 0000000..8ba5261
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/steps/VisitorSteps.java
@@ -0,0 +1,171 @@
+/*
+ * 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.steps;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.ast.visitor.GenericListVisitorAdapter;
+import com.github.javaparser.ast.visitor.GenericVisitorAdapter;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+import com.github.javaparser.visitors.PositionTestVisitor;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class VisitorSteps {
+
+    /* Fields used to maintain step state within this step class */
+    private VoidVisitorAdapter<AtomicReference<String>> toUpperCaseVariableNameVisitor;
+    private VoidVisitorAdapter<AtomicReference<String>> collectVariableNameVisitor;
+    private PositionTestVisitor positionTestVisitor;
+    private GenericVisitorAdapter<String, Void> nameReturningVisitor;
+    private GenericListVisitorAdapter<String, Void> allNameReturningVisitor;
+    private AtomicReference<String> collectedVariableName;
+    private String returnedVariableName;
+    private List<String> returnedVariableNames;
+
+    /* Map that maintains shares state across step classes.  If manipulating the objects in the map you must update the state */
+    private Map<String, Object> state;
+
+    public VisitorSteps(Map<String, Object> state) {
+        this.state = state;
+    }
+
+    @Given("a VoidVisitorAdapter with a visit method that changes variable names to uppercase")
+    public void givenAVoidVisitorAdapterWithAVisitMethodThatChangesVariableNamesToUppercase() {
+        toUpperCaseVariableNameVisitor = new VoidVisitorAdapter<AtomicReference<String>>() {
+            @Override
+            public void visit(VariableDeclarator n, AtomicReference<String> arg) {
+                n.setName(n.getNameAsString().toUpperCase());
+            }
+        };
+    }
+
+    @Given("a VoidVisitorAdapter with a visit method and collects the variable names")
+    public void givenAVoidVisitorAdapterWithAVisitMethodThatCollectsTheVariableName() {
+        collectVariableNameVisitor = new VoidVisitorAdapter<AtomicReference<String>>() {
+            @Override
+            public void visit(VariableDeclarator n, AtomicReference<String> arg) {
+                arg.set(arg.get() + n.getName() + ";");
+            }
+
+            @Override
+            public void visit(Parameter n, AtomicReference<String> arg) {
+                arg.set(arg.get() + n.getName() + ";");
+            }
+        };
+    }
+
+    @Given("a GenericVisitorAdapter with a visit method that returns variable names")
+    public void givenAGenericVisitorAdapterWithAVisitMethodThatReturnsVariableNames() {
+        nameReturningVisitor = new GenericVisitorAdapter<String, Void>() {
+            @Override
+            public String visit(VariableDeclarator n, Void arg) {
+                return n.getNameAsString();
+            }
+        };
+    }
+
+    @Given("a GenericListVisitorAdapter with a visit method that returns all variable names")
+    public void givenAGenericListVisitorAdapterWithAVisitMethodThatReturnsAllVariableNames() {
+        allNameReturningVisitor = new GenericListVisitorAdapter<String, Void>() {
+            @Override
+            public List<String> visit(VariableDeclarator n, Void arg) {
+                return Collections.singletonList(n.getNameAsString());
+            }
+        };
+    }
+
+    @Given("a VoidVisitorAdapter with a visit method that asserts sensible line positions")
+    public void givenAVoidVisitorAdapterWithAVisitMethodThatAssertsSensibleLinePositions() {
+        positionTestVisitor = new PositionTestVisitor();
+    }
+
+    @When("the CompilationUnit is cloned to the second CompilationUnit")
+    public void whenTheSecondCompilationUnitIsCloned() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        CompilationUnit compilationUnit2 = (CompilationUnit) compilationUnit.accept(new CloneVisitor(), null);
+        state.put("cu2", compilationUnit2);
+    }
+
+    @When("the CompilationUnit is visited by the to uppercase visitor")
+    public void whenTheCompilationUnitIsVisitedByTheVistor() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        toUpperCaseVariableNameVisitor.visit(compilationUnit, null);
+        state.put("cu1", compilationUnit);
+    }
+
+    @When("the CompilationUnit is visited by the variable name collector visitor")
+    public void whenTheCompilationUnitIsVisitedByTheVariableNameCollectorVisitor() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        collectedVariableName = new AtomicReference<>("");
+        collectVariableNameVisitor.visit(compilationUnit, collectedVariableName);
+    }
+
+    @When("the CompilationUnit is visited by the visitor that returns variable names")
+    public void whenTheCompilationUnitIsVisitedByTheVisitorThatReturnsVariableNames() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        returnedVariableName = nameReturningVisitor.visit(compilationUnit, null);
+    }
+
+    @When("the CompilationUnit is visited by the visitor that returns all variable names")
+    public void whenTheCompilationUnitIsVisitedByTheVisitorThatReturnsAllVariableNames() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        returnedVariableNames = allNameReturningVisitor.visit(compilationUnit, null);
+    }
+
+    @When("the CompilationUnit is visited by the PositionTestVisitor")
+    public void whenTheCompilationUnitIsVisitedByThePositionTestVisitor() {
+        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
+        compilationUnit.accept(positionTestVisitor, null);
+    }
+
+    @Then("the collected variable name is \"$nameUnderTest\"")
+    public void thenTheCollectedVariableNameIs(String nameUnderTest) {
+        assertThat(collectedVariableName.get(), is(nameUnderTest));
+    }
+
+    @Then("the return variable name is \"$nameUnderTest\"")
+    public void thenTheReturnVariableNameIs(String nameUnderTest) {
+        assertThat(returnedVariableName, is(nameUnderTest));
+    }
+
+    @Then("the first return variable name is \"$nameUnderTest\"")
+    public void thenTheFirstReturnVariableNameIs(String nameUnderTest) {
+        assertThat(returnedVariableNames.get(0), is(nameUnderTest));
+    }
+
+    @Then("the total number of nodes visited is $expectedCount")
+    public void thenTheTotalNumberOfNodesVisitedIs(int expectedCount) {
+        assertThat(positionTestVisitor.getNumberOfNodesVisited(), is(expectedCount));
+    }
+}
diff --git a/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/visitors/PositionTestVisitor.java b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/visitors/PositionTestVisitor.java
new file mode 100644
index 0000000..d6755de
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/java/com/github/javaparser/visitors/PositionTestVisitor.java
@@ -0,0 +1,553 @@
+/*
+ * 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.visitors;
+
+import com.github.javaparser.Position;
+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.expr.*;
+import com.github.javaparser.ast.stmt.*;
+import com.github.javaparser.ast.type.*;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
+import static org.hamcrest.core.Is.is;
+
+public class PositionTestVisitor extends VoidVisitorAdapter<Object> {
+
+    private int numberOfNodesVisited;
+
+    @Override
+    public void visit(final AnnotationDeclaration n, final Object arg) {
+        doTest(n);
+        doTest(n.getName());
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final AnnotationMemberDeclaration n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ArrayAccessExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ArrayCreationExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ArrayInitializerExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final AssertStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final AssignExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final BinaryExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final BlockComment n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final BlockStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final BooleanLiteralExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final BreakStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final CastExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final CatchClause n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(LambdaExpr n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(MethodReferenceExpr n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(TypeExpr n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final CharLiteralExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ClassExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ClassOrInterfaceDeclaration n, final Object arg) {
+        doTest(n);
+        doTest(n.getName());
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ClassOrInterfaceType n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final CompilationUnit n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ConditionalExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ConstructorDeclaration n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ContinueStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final DoStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final DoubleLiteralExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final EmptyStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final EnclosedExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final EnumConstantDeclaration n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final EnumDeclaration n, final Object arg) {
+        doTest(n);
+        doTest(n.getName());
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ExplicitConstructorInvocationStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ExpressionStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final FieldAccessExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final FieldDeclaration n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ForEachStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ForStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final IfStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final InitializerDeclaration n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final InstanceOfExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final IntegerLiteralExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final JavadocComment n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final LabeledStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final LineComment n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final LongLiteralExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final MarkerAnnotationExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final MemberValuePair n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final MethodCallExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final MethodDeclaration n, final Object arg) {
+        doTest(n);
+        doTest(n.getName());
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final NameExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final NormalAnnotationExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final NullLiteralExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ObjectCreationExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final PackageDeclaration n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final Parameter n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final PrimitiveType n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final Name n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(SimpleName n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(ArrayType n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(ArrayCreationLevel n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final IntersectionType n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(UnionType n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ReturnStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final SingleMemberAnnotationExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final StringLiteralExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final SuperExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final SwitchEntry n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final SwitchStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final SynchronizedStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ThisExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final ThrowStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final TryStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final LocalClassDeclarationStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final TypeParameter n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final UnaryExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final VariableDeclarationExpr n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final VariableDeclarator n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final VoidType n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final WhileStmt n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(final WildcardType n, final Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    @Override
+    public void visit(UnknownType n, Object arg) {
+        doTest(n);
+        super.visit(n, arg);
+    }
+
+    private void doTest(final Node node) {
+        Position begin = node.getRange().get().begin;
+        Position end = node.getRange().get().end;
+        assertThat(begin.line, is(greaterThanOrEqualTo(0)));
+        assertThat(begin.column, is(greaterThanOrEqualTo(0)));
+        assertThat(end.line, is(greaterThanOrEqualTo(0)));
+        assertThat(end.column, is(greaterThanOrEqualTo(0)));
+
+        if (begin.line == end.line) {
+            assertThat(begin.column, is(lessThanOrEqualTo(end.column)));
+        } else {
+            assertThat(begin.line, is(lessThanOrEqualTo(end.line)));
+        }
+        numberOfNodesVisited++;
+    }
+
+    public int getNumberOfNodesVisited() {
+        return numberOfNodesVisited;
+    }
+}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/comment_attribution_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_attribution_scenarios.story
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/comment_attribution_scenarios.story
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_attribution_scenarios.story
diff --git a/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_parsing_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_parsing_scenarios.story
new file mode 100644
index 0000000..bfcd5ed
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comment_parsing_scenarios.story
@@ -0,0 +1,281 @@
+Scenario: A Class With Line Comments is processed by the Comments Parser
+
+Given the class:
+package japa.parser.comments;
+
+public class ClassWithLineComments {
+
+    public void aMethod(){
+        // first comment
+        int a=0; // second comment
+        // third comment
+        // fourth comment
+    }
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 4
+Then line comment 1 is " first comment"
+Then line comment 2 is " second comment"
+Then line comment 3 is " third comment"
+Then line comment 4 is " fourth comment"
+Then the line comments have the following positions:
+|beginLine|beginColumn|endLine|endColumn|
+|6|9|6|24|
+|7|18|7|34|
+|8|9|8|24|
+|9|9|9|25|
+
+Scenario: A Class With Block Comments is processed by the Comments Parser
+
+Given the class:
+package japa.parser.comments;
+
+/* comment which is not attributed to the class, it floats around as an orphan */
+/* comment to a class */
+public class ClassWithBlockComments {
+
+    /* comment to a method */
+    void foo(){};
+
+    /* comment put randomly in class:
+
+    another orphan.
+    It spans over more lines */
+
+}
+
+/* a comment lost inside a compilation unit. It is orphan, I am sure you got this one */
+When the class is parsed by the comment parser
+Then the total number of comments is 5
+Then block comment 1 is " comment which is not attributed to the class, it floats around as an orphan "
+Then block comment 2 is " comment to a class "
+Then block comment 3 is " comment to a method "
+Then block comment 4 is " comment put randomly in class:    another orphan.    It spans over more lines "
+Then block comment 5 is " a comment lost inside a compilation unit. It is orphan, I am sure you got this one  "
+Then the block comments have the following positions:
+|beginLine|beginColumn|endLine|endColumn|
+|3|1|3|81|
+|4|1|4|24|
+|7|5|7|29|
+|10|5|13|31|
+|17|1|17|88|
+
+
+Scenario: A Class With Javadoc Comments is processed by the Comments Parser
+
+Given the class:
+package japa.parser.comments;
+
+/** a proper javadoc comment */
+public class ClassWithJavadocComments {
+
+    void foo(){};
+
+
+}
+/** a floating javadoc comment */
+When the class is parsed by the comment parser
+Then the total number of comments is 2
+Then Javadoc comment 1 is " a proper javadoc comment "
+Then Javadoc comment 2 is " a floating javadoc comment "
+Then the Javadoc comments have the following positions:
+|beginLine|beginColumn|endLine|endColumn|
+|3|1|3|31|
+|10|1|10|33|
+
+
+
+Scenario: A Class With Orphan Comments is processed by the Comments Parser
+
+Given the class:
+package japa.parser.comments;
+
+/**Javadoc associated with the class*/
+public class ClassWithOrphanComments {
+    //a first comment floating in the class
+
+    //comment associated to the method
+    void foo(){
+        /*comment floating inside the method*/
+    }
+
+    //a second comment floating in the class
+}
+
+//Orphan comment inside the CompilationUnit
+When the class is parsed by the comment parser
+Then the total number of comments is 6
+Then line comment 1 is "a first comment floating in the class"
+Then line comment 2 is "comment associated to the method"
+Then line comment 3 is "a second comment floating in the class"
+Then block comment 1 is "comment floating inside the method"
+Then Javadoc comment 1 is "Javadoc associated with the class"
+
+
+Scenario: A Class With Orphan Comments is processed by the Comments Parser
+
+Given the class:
+/*CompilationUnitComment*/
+package japa.parser.comments;
+
+public class ClassWithMixedStyleComments {
+    // line comment
+    int a = 0;
+    // another line comment
+    int b = 0;
+    // line comment
+    int c = 0;
+    /* multi-line
+       comment
+    */
+    int d = 0;
+    /**
+     * multi-line
+     */
+    int e = 0;
+    // final comment
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 7
+Then the line comments have the following positions:
+|beginLine|beginColumn|endLine|endColumn|
+|5|5|5|19|
+|7|5|7|27|
+|9|5|9|19|
+|19|5|19|20|
+Then the block comments have the following positions:
+|beginLine|beginColumn|endLine|endColumn|
+|1|1|1|26|
+|11|5|13|6|
+Then the Javadoc comments have the following positions:
+|beginLine|beginColumn|endLine|endColumn|
+|15|5|17|7|
+
+Scenario: A method containing two consecutive line comments is parsed correctly
+
+Given the class:
+class A {
+  void aMethod(){
+     // foo
+     // bar
+     int a;
+  }
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 2
+Then line comment 1 is " foo"
+Then line comment 2 is " bar"
+
+Scenario: Comments from a file with an non-UTF-8 encoding are parsed correctly
+
+When read sample "ClassInLatin1" using encoding "ISO-8859-1"
+Then the total number of comments is 3
+Then line comment 2 is " A l'émej in piasì che sent dësgust."
+
+Scenario: Should not recognize /*/ as a comment
+
+Given the class:
+/*/
+class Foo {}
+When the class is parsed by the comment parser
+Then the total number of comments is 0
+
+Given the class:
+/*/
+class Foo {}
+Then the Java parser cannot parse it because of an error
+
+Scenario: Should recognize /*/ inside a block comment
+
+Given the class:
+/* Foo /*/
+When the class is parsed by the comment parser
+Then the total number of comments is 1
+Then block comment 1 is " Foo /"
+
+Scenario: A Class With Character Literal is processed by the Comments Parser
+Given the class:
+class A {
+    /** comment1 */
+    private char c = '"';
+    /** comment2 */
+    private String d;
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 2
+Then Javadoc comment 1 is "comment1"
+Then Javadoc comment 2 is "comment2"
+
+Scenario: Double slash in string does not mess up comments parsing
+Given the class:
+public class b {
+
+    public void m1() {
+        String s = "\\";
+    }
+
+    /**
+     * Comment
+    */
+    public void m2() {
+        return;
+    }
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 1
+
+Scenario: Triple slash in string does not mess up comments parsing
+Given the class:
+public class b {
+
+    public void m1() {
+        String s = "\\\" // still in string";
+    }
+
+    /**
+     * Comment
+    */
+    public void m2() {
+        return;
+    }
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 1
+
+Scenario: Four slashes in string does not mess up comments parsing
+Given the class:
+public class b {
+
+    public void m1() {
+        String s = "\\\\" // out of the string";
+        ;
+    }
+
+    /**
+     * Comment
+    */
+    public void m2() {
+        return;
+    }
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 2
+
+Scenario: Five slashes in string does not mess up comments parsing
+Given the class:
+public class b {
+
+    public void m1() {
+        String s = "\\\\\" // still in string";
+        ;
+    }
+
+    /**
+     * Comment
+    */
+    public void m2() {
+        return;
+    }
+}
+When the class is parsed by the comment parser
+Then the total number of comments is 1
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/comparing_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comparing_scenarios.story
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/comparing_scenarios.story
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/comparing_scenarios.story
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/manipulation_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/manipulation_scenarios.story
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/manipulation_scenarios.story
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/manipulation_scenarios.story
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/parsing_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/parsing_scenarios.story
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/parsing_scenarios.story
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/parsing_scenarios.story
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/position_range_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/position_range_scenarios.story
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/position_range_scenarios.story
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/position_range_scenarios.story
diff --git a/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/pretty_printing_java_concepts.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/pretty_printing_java_concepts.story
new file mode 100644
index 0000000..ebcf824
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/pretty_printing_java_concepts.story
@@ -0,0 +1,400 @@
+Scenario: Check a whole lot of things at once that should be separate tests
+
+Given the class in the file "JavaConcepts.java"
+When the class is parsed by the Java parser
+Then it is printed as:
+package japa.bdd.samples;
+
+import com.github.javaparser.JavaParser;
+import japa.parser.ParseException;
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.Ignore;
+import java.io.*;
+import java.util.*;
+
+@Ignore
+@Deprecated
+public class JavaConcepts<T extends List<int[]>, X> extends Base implements Serializable {
+
+    static Class clz1 = String.class;
+
+    protected Class clz2 = (String.class);
+
+    Class clz3 = int.class;
+
+    Class clz4 = (int.class);
+
+    int[] arr = new int[10];
+
+    byte bye = 0;
+
+    byte[] byebye = null;
+
+    short sh1, sh2 = 1;
+
+    int intWithUnderscore = 1234_5678;
+
+    long longWithUnderscore = 1234_5678L;
+
+    float floatWithUnderscore = 1_234.5_678f;
+
+    float floatWithUnderscoreAndExponent = 1_234e1_0f;
+
+    double doubleWithUnderscore = 1_234.5_678;
+
+    double doubleWithUnderscoreAndExponent = 1_234e1_0;
+
+    int binaryLiteral = 0b101101;
+
+    List<String>[][] arrLS = (List<String>[][]) new List<?>[10][];
+
+    {
+        int z = 0, y = 0;
+        int a = (z) + y;
+        a = (+z) + y;
+        byte b = (byte) +y;
+    }
+
+    List<String> diamond1 = new LinkedList<>();
+
+    @Deprecated()
+    static class Ugly {
+
+        static int x = 0;
+
+        public static void main(String[] args) {
+            x = +x;
+            x = ~x;
+            --x;
+            boolean b = !false;
+            x &= 2;
+            x |= 2;
+            x ^= 2;
+            x -= 2;
+            x %= 2;
+            x /= 2;
+            x *= 2;
+            x <<= 2;
+            x >>= 2;
+            x >>>= 2;
+            b = b || false;
+            b = b | false;
+            b = b & false;
+            b = b ^ false;
+            b = b != false;
+            b = x > 1;
+            b = x < 1;
+            b = x >= 1;
+            b = x <= 1;
+            x = x << 1;
+            x = x >> 1;
+            x = x >>> 1;
+            x = x - 1;
+            x = x * 1;
+            x = x % 1;
+            x = x / 1;
+        }
+    }
+
+    @Deprecated()
+    int[][][][] arr2 = new int[10][2][1][0];
+
+    volatile float fff = 0x1.fffeP+127f;
+
+    char cc = 'a';
+
+    int[][] arr3 = { { 1, 2 }, { 3, 4 } };
+
+    static int[][] arr4 = {};
+
+    public static JavaConcepts t;
+
+    static {
+        arr4 = new int[][] { { 2 }, { 1 } };
+    }
+
+    {
+        arr3 = new int[][] { { 2 }, { 1 } };
+    }
+
+    public enum Teste {
+
+        asc, def
+    }
+
+    public enum Sexo {
+
+        m, @Deprecated
+        f;
+
+        public enum Sexo_ implements Serializable, Cloneable {
+        }
+
+        private Sexo() {
+        }
+    }
+
+    @Deprecated
+    public enum Enum {
+
+        m(1) {
+
+            @Override
+            void mm() {
+            }
+        }
+        , f(2) {
+
+            void mm() {
+            }
+        }
+        ;
+
+        native void nnn();
+
+        transient int x;
+
+        private Enum(int x) {
+            this.x = x;
+        }
+
+        abstract void mm();
+    }
+
+    strictfp double ddd() {
+        return 0.0;
+    }
+
+    public <T, E> JavaConcepts(int x) {
+        this.arr[0] = x;
+        T val1 = null;
+        E val2 = null;
+        super.<T, E>check2(val1, val2);
+        boolean b = true, y = false;
+        abstract class X {
+
+            int i = 0;
+
+            public <D> X() {
+            }
+
+            public void m() {
+            }
+        }
+        @Deprecated
+        final class Y extends X {
+
+            public Y() {
+                super();
+                JavaConcepts.this.cc = 'c';
+                super.i = 1;
+                Y.super.m();
+            }
+
+            public Y(int y) {
+                super();
+            }
+
+            public Y(long x) {
+                this();
+            }
+        }
+    }
+
+    public <T> JavaConcepts(String str) {
+    }
+
+    private class QWE extends JavaConcepts<List<int[]>, String> {
+
+        @Deprecated
+        final int z = 0;
+
+        int i = (int) -1;
+
+        public QWE(String... x) {
+            <String>super(x[0]);
+        }
+
+        public QWE(int... x) {
+            super(x[0]);
+            i = x[0];
+            assert true;
+            assert 1 == 1 : 2;
+            {
+                int iii = 3;
+                iii += 3;
+            }
+            label: {
+                int iii = 1;
+            }
+            ;
+            ;
+            int min = -2147483648;
+            long sl = 123123123123l;
+            long minl = -9223372036854775808L;
+            switch(i) {
+            }
+            ll: switch(i) {
+                case 1:
+                    System.out.println(1);
+                    break ll;
+                default:
+                    {
+                        System.out.println("default");
+                        break;
+                    }
+                case 2:
+                    if (t instanceof Base) {
+                        System.out.println(1);
+                    }
+                    i++;
+                    ++i;
+            }
+        }
+
+        private synchronized int[] doSomething() {
+            List<? extends Number> x = new ArrayList<Integer>();
+            return new int[] { 1 };
+        }
+    }
+
+    public static void main(String[] args) throws ParseException, IOException {
+        int x = 2;
+        CompilationUnit cu = parse(new File("src/japa/parser/javacc/Parser.java"));
+        System.out.println(cu);
+        JavaConcepts teste = new JavaConcepts(2);
+        JavaConcepts.QWE qwe = teste.new QWE(1);
+        if (1 + 1 == 2) {
+            teste = null;
+            teste = new JavaConcepts(1);
+        } else {
+            x = 3;
+            teste = new JavaConcepts(1);
+            x = x == 0 ? 2 : 4;
+        }
+        if (true)
+            x = 1;
+        else
+            x = 3;
+        if (true)
+            x = 1;
+        else if (false)
+            x = 3;
+        else
+            x = 2;
+        while (true) {
+            xxx: while (x == 3) continue xxx;
+            break;
+        }
+        do {
+            x++;
+        } while (x < 100);
+        do x++; while (x < 100);
+        for (@Deprecated int i : arr4[0]) {
+            x--;
+        }
+        for (@Deprecated final int i = 0, j = 1; i < 10; x++) {
+            break;
+        }
+        int i, j;
+        for (i = 0, j = 1; i < 10 && j < 2; i++, j--) {
+            break;
+        }
+    }
+
+    public static CompilationUnit parse(@Deprecated File file) throws ParseException, IOException {
+        String a = ((String) "qwe");
+        String x = ((String) clz1.getName());
+        int y = ((Integer) (Object) x).intValue();
+        synchronized (file) {
+            file = null;
+            file = new File("");
+        }
+        try {
+            if (file == null) {
+                throw new NullPointerException("blah");
+            }
+        } catch (final NullPointerException e) {
+            System.out.println("catch");
+        } catch (RuntimeException e) {
+            System.out.println("catch");
+        } finally {
+            System.out.println("finally");
+        }
+        try {
+            if (file == null) {
+                throw new NullPointerException("blah");
+            }
+        } finally {
+            System.out.println("finally");
+        }
+        try {
+            if (file == null) {
+                throw new NullPointerException("blah");
+            }
+        } catch (RuntimeException e) {
+            System.out.println("catch");
+        }
+        try (InputStream in = createInputStream()) {
+            System.out.println(in);
+        } catch (IOException e) {
+            System.out.println("catch");
+        }
+        try (InputStream in = createInputStream();
+            InputStream in2 = createInputStream()) {
+            System.out.println(in);
+        } catch (IOException e) {
+            System.out.println("catch");
+        }
+        try (InputStream in = createInputStream()) {
+            System.out.println(in);
+        }
+        try {
+            System.out.println("whatever");
+        } catch (RuntimeException e) {
+            System.out.println(e);
+        } catch (final Exception | Error e) {
+            System.out.println(e);
+        }
+        return JavaParser.parse(file);
+    }
+
+    class A<T extends Integer & Serializable> implements XXX, Serializable {
+
+        public <ABC> A(Integer integer, ABC string) throws Exception, IOException {
+        }
+    }
+
+    private <Y> void x(Map<? extends X, ? super T> x) {
+        @Deprecated
+        Comparator c = new Comparator() {
+
+            public int compare(Object o1, Object o2) {
+                try {
+                    A<Integer> a = new <String> A<Integer>(new Integer(11), "foo") {
+                    };
+                } catch (Exception e) {
+                }
+                return 0;
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                return super.equals(obj);
+            }
+        };
+    }
+
+    private static InputStream createInputStream() {
+        return new ByteArrayInputStream(null);
+    }
+}
+
+class Base {
+
+    public <A, B> void check2(A val1, B val2) {
+    }
+}
+
+interface XXX extends Serializable, Cloneable {
+}
diff --git a/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/pretty_printing_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/pretty_printing_scenarios.story
new file mode 100644
index 0000000..a19f877
--- /dev/null
+++ b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/pretty_printing_scenarios.story
@@ -0,0 +1,520 @@
+Scenario: When printing the instantiation we should use the right amount of spaces
+
+Given the class:
+public class A {
+    Object foo = new Object();
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class A {
+
+    Object foo = new Object();
+}
+
+
+Scenario: When printing the lambda expression we should use the right indentation
+
+Given the class:
+public class B {
+	Runnable runnable = ()-> System.out.println("running");
+    Consumer<Integer> consumer = i->{ i+=1; System.out.println(i);};
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class B {
+
+    Runnable runnable = () -> System.out.println("running");
+
+    Consumer<Integer> consumer = i -> {
+        i += 1;
+        System.out.println(i);
+    };
+}
+
+
+Scenario: Printing orphan comments in empty method
+Given the class:
+class A {
+    public void helloWorld(String greeting, String name) {
+        //sdfsdfsdf
+            //sdfds
+        /*
+                            dgfdgfdgfdgfdgfd
+         */
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+class A {
+
+    public void helloWorld(String greeting, String name) {
+    // sdfsdfsdf
+    // sdfds
+    /*
+                            dgfdgfdgfdgfdgfd
+         */
+    }
+}
+
+
+
+Scenario: Printing orphan comments in empty method (issue 192)
+Given the class:
+public class StepImplementation {
+    @Step("A step")
+    public void contextStep() {
+        // Foo bar
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class StepImplementation {
+
+    @Step("A step")
+    public void contextStep() {
+    // Foo bar
+    }
+}
+
+
+Scenario: Printing orphan comments in for loop (issue 192)
+Given the class:
+public class StepImplementation {
+    public void contextStep() {
+        for (int i = 0; i < 5; i++) {
+            // foo bar
+        }
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class StepImplementation {
+
+    public void contextStep() {
+        for (int i = 0; i < 5; i++) {
+        // foo bar
+        }
+    }
+}
+
+
+Scenario: Printing orphan and attributed comments in for loop (issue 192)
+Given the class:
+public class StepImplementation {
+public void contextStep() {
+        for (int i = 0; i < 5; i++) {
+            // foo bar
+            System.out.println();
+            // another foo bar
+        }
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class StepImplementation {
+
+    public void contextStep() {
+        for (int i = 0; i < 5; i++) {
+            // foo bar
+            System.out.println();
+        // another foo bar
+        }
+    }
+}
+
+
+Scenario: An empty Enum is printed correctly
+Given the compilation unit:
+package test; enum XYZ {}
+When the class is parsed by the Java parser
+Then it is printed as:
+package test;
+
+enum XYZ {
+}
+
+Scenario: An enum without fields has no () on its members
+Given the compilation unit:
+package test; enum XYZ {A,B,C}
+When the class is parsed by the Java parser
+Then it is printed as:
+package test;
+
+enum XYZ {
+
+    A, B, C
+}
+
+Scenario: Strings with escaped newlines are parsed correctly
+Given the class:
+class A {
+    public void helloWorld(String greeting, String name) {
+        return "hello\nworld";
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+class A {
+
+    public void helloWorld(String greeting, String name) {
+        return "hello\nworld";
+    }
+}
+
+Scenario: A multi-catch is printed correctly
+Given the class:
+class A {
+    public void a() {
+        try {
+        } catch (IndexOutOfBoundException | IOException e) {
+        }
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+class A {
+
+    public void a() {
+        try {
+        } catch (IndexOutOfBoundException | IOException e) {
+        }
+    }
+}
+
+Scenario: An empty import does not fail
+Given the class:
+package a.b.c;
+
+;
+When the class is parsed by the Java parser
+Then it is printed as:
+package a.b.c;
+
+Scenario: we can parse blocks
+Given the block:
+{
+    a=2;
+    b=3;
+}
+When the block is parsed by the Java parser
+Then it is printed as:
+{
+    a = 2;
+    b = 3;
+}
+
+Scenario: we can parse statements
+Given the statement:
+while (true) {
+}
+When the statement is parsed by the Java parser
+Then it is printed as:
+while (true) {
+}
+
+Scenario: we can parse static on demand imports
+Given the import:
+import static a.b.c.Abc.*;
+When the import is parsed by the Java parser
+Then it is printed as:
+import static a.b.c.Abc.*;
+
+Scenario: we can parse static type imports
+Given the import:
+import static a.b.c.Abc;
+When the import is parsed by the Java parser
+Then it is printed as:
+import static a.b.c.Abc;
+
+Scenario: we can parse on demand imports
+Given the import:
+import a.b.c.*;
+When the import is parsed by the Java parser
+Then it is printed as:
+import a.b.c.*;
+
+Scenario: we can parse type imports
+Given the import:
+import a.b.c.Abc;
+When the import is parsed by the Java parser
+Then it is printed as:
+import a.b.c.Abc;
+
+Scenario: we can parse annotations
+Given the annotation:
+@Abc
+When the annotation is parsed by the Java parser
+Then it is printed as:
+@Abc
+
+Scenario: we can parse body declarations
+Given the body:
+String author();
+When the annotation body declaration is parsed by the Java parser
+Then it is printed as:
+String author();
+
+Scenario: we can parse class body declarations
+Given the body:
+public int xyz() {}
+When the class body declaration is parsed by the Java parser
+Then it is printed as:
+public int xyz() {
+}
+
+Scenario: we can parse interface body declarations
+Given the body:
+int xyz();
+When the interface body declaration is parsed by the Java parser
+Then it is printed as:
+int xyz();
+
+Scenario: It doesn't throw NPE when using a modifierVisitorAdapter
+Given the class:
+public class Example {
+  private String mString;
+  public Example(String arg) {
+    mString = arg;
+  }
+}
+When the class is parsed by the Java parser
+When the class is visited by an empty ModifierVisitorAdapter
+Then it is printed as:
+public class Example {
+
+    private String mString;
+
+    public Example(String arg) {
+        mString = arg;
+    }
+}
+
+Scenario: JavaDoc OR comment is printed, not both.
+Given the class:
+public class Foo {
+    /** This line gets duplicated */
+    public void foo() {
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class Foo {
+
+    /**
+     * This line gets duplicated
+     */
+    public void foo() {
+    }
+}
+
+Scenario: various lamba casts (issue 418)
+Given the class:
+public class TestLambda {
+    void okMethod() {
+        return (ITF) () -> {
+            return true;
+        };
+    }
+    void faliingMethod() {
+        testThis(check ? null : (ITF) () -> {
+            return true;
+        });
+    }
+}
+When the class body declaration is parsed by the Java parser
+Then it is printed as:
+public class TestLambda {
+
+    void okMethod() {
+        return (ITF) () -> {
+            return true;
+        };
+    }
+
+    void faliingMethod() {
+        testThis(check ? null : (ITF) () -> {
+            return true;
+        });
+    }
+}
+
+Scenario: Duplicate methods are not a parsing error (#416)
+Given the class:
+public class Foo {
+    public void foo() {
+    }
+    public void foo() {
+    }
+    public void foo() {
+    }
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class Foo {
+
+    public void foo() {
+    }
+
+    public void foo() {
+    }
+
+    public void foo() {
+    }
+}
+
+Scenario: Both array syntaxes are supported (#416)
+Given the class:
+public class Foo {
+    public void m1(boolean[] boolArray) {}
+    public void m1(boolean boolArray[]) {}
+    public void m1(boolean[] boolArray[]) {}
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+public class Foo {
+
+    public void m1(boolean[] boolArray) {
+    }
+
+    public void m1(boolean[] boolArray) {
+    }
+
+    public void m1(boolean[][] boolArray) {
+    }
+}
+
+
+Scenario: Array parts can be annotated
+Given the class:
+class Foo {
+    void m1(@Boo boolean @Index1 [] @ Index2 [] boolArray) {}
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+class Foo {
+
+    void m1(@Boo boolean @Index1 [] @Index2 [] boolArray) {
+    }
+}
+
+Scenario: Annotations are supported on annotations
+Given the class:
+@C @interface D {
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+@C
+@interface D {
+}
+
+Scenario: Annotations are supported on interfaces
+Given the class:
+@C interface Abc {
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+@C
+interface Abc {
+}
+
+Scenario: Annotations are supported on enums
+Given the class:
+@C enum Abc {
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+@C
+enum Abc {
+}
+
+Scenario: Annotations are supported on classes (issue 436 is the commented part)
+Given the compilation unit:
+@C
+public class Abc<@C A, @C X extends @C String & @C Serializable> {
+
+	@C int @C[] @C []f;
+
+	@C
+	public Abc(@C int p, List<@C ? extends Object> aa){
+		@C int b;
+	}
+	public @C void a(@C int o) {
+/*		try {
+			throw new IOException();
+		} catch (@C NullPointerException | @C IOException e) {
+		}
+*/	}
+}
+When the compilation unit is parsed by the Java parser
+Then it is printed as:
+@C
+public class Abc<@C A, @C X extends @C String & @C Serializable> {
+
+    @C
+    int @C [] @C [] f;
+
+    @C
+    public Abc(@C int p, List<@C ? extends Object> aa) {
+        @C
+        int b;
+    }
+
+    @C
+    public void a(@C int o) {
+    /*		try {
+			throw new IOException();
+		} catch (@C NullPointerException | @C IOException e) {
+		}
+*/
+    }
+}
+
+
+Scenario: Annotations are supported inside catch (issue 436)
+Given the compilation unit:
+public class Abc {
+	public void a() {
+		try {
+		} catch (@C NullPointerException | @C IOException e) {
+		}
+	}
+}
+When the compilation unit is parsed by the Java parser
+Then it is printed as:
+public class Abc {
+
+    public void a() {
+        try {
+        } catch (@C NullPointerException | @C IOException e) {
+        }
+    }
+}
+
+Scenario: Inner class notation does not confuse annotations (#107)
+Given the class:
+class A extends @Ann1 B.@Ann2 C {
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+class A extends @Ann1 B.@Ann2 C {
+}
+
+Scenario: Make sure interface extends can be annotated
+Given the class:
+interface A extends @X B, @Y C, @Z D {
+}
+When the class is parsed by the Java parser
+Then it is printed as:
+interface A extends @X B, @Y C, @Z D {
+}
+
+Scenario: default modifier isn't printed twice
+Given the class:
+interface X {default String author(){}}
+When the annotation body declaration is parsed by the Java parser
+Then it is printed as:
+interface X {
+
+    default String author() {
+    }
+}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/samples/ClassInLatin1.java b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/samples/ClassInLatin1.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/samples/ClassInLatin1.java
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/samples/ClassInLatin1.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/samples/JavaConcepts.java b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/samples/JavaConcepts.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/samples/JavaConcepts.java
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/samples/JavaConcepts.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/samples/package-info.java b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/samples/package-info.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/samples/package-info.java
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/samples/package-info.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/visitor_scenarios.story b/javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/visitor_scenarios.story
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bdd/visitor_scenarios.story
rename to javaparser-core-testing-bdd/src/test/resources/com/github/javaparser/visitor_scenarios.story
diff --git a/javaparser-core-testing/pom.xml b/javaparser-core-testing/pom.xml
new file mode 100644
index 0000000..61e07c9
--- /dev/null
+++ b/javaparser-core-testing/pom.xml
@@ -0,0 +1,108 @@
+<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.14.10-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>javaparser-core-testing</artifactId>
+    <description>The test suite for javaparser-core</description>
+
+    <licenses>
+        <license>
+            <name>GNU Lesser General Public License</name>
+            <url>http://www.gnu.org/licenses/lgpl-3.0.html</url>
+            <distribution>repo</distribution>
+        </license>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+            <comments>A business-friendly OSS license</comments>
+        </license>
+    </licenses>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>jacoco-initialize</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>jacoco-site</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <encoding>UTF-8</encoding>
+                            <outputDirectory>${basedir}/target/classes</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>../javaparser-core/target/classes</directory>
+                                    <filtering>false</filtering>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <!-- no need to release this module -->
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>com.github.javaparser</groupId>
+            <artifactId>javaparser-core</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>3.11.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>3.11.0</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/CommentsInserterTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/CommentsInserterTest.java
new file mode 100644
index 0000000..3f906e9
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/CommentsInserterTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.comments.CommentsCollection;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseResource;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CommentsInserterTest {
+    private String makeFilename(String sampleName) {
+        return "com/github/javaparser/issue_samples/" + sampleName + ".java.txt";
+    }
+
+    private ParseResult<CompilationUnit> parseSample(String sampleName) throws IOException {
+        Provider p = Providers.resourceProvider(
+                makeFilename(sampleName));
+        return new JavaParser().parse(ParseStart.COMPILATION_UNIT, p);
+    }
+
+    /**
+     * Issue: "When there is a String constant "\\" compilationUnit ignores all further comments"
+     */
+    @Test
+    void issue290() throws IOException {
+        ParseResult result = parseSample("Issue290");
+        CommentsCollection cc = (CommentsCollection) result.getCommentsCollection().get();
+        assertEquals(1, cc.getLineComments().size());
+        assertEquals(1, cc.getJavadocComments().size());
+    }
+
+    @Test
+    void issue624() throws IOException {
+        parseResource(makeFilename("Issue624"));
+        // Should not fail
+    }
+
+    @Test
+    void issue200EnumConstantsWithCommentsForceVerticalAlignment() {
+        CompilationUnit cu = parse("public enum X {" + EOL +
+                "    /** const1 javadoc */" + EOL +
+                "    BORDER_CONSTANT," + EOL +
+                "    /** const2 javadoc */" + EOL +
+                "    ANOTHER_CONSTANT" + EOL +
+                "}");
+        assertEqualsNoEol("public enum X {\n" +
+                "\n" +
+                "    /**\n" +
+                "     * const1 javadoc\n" +
+                "     */\n" +
+                "    BORDER_CONSTANT,\n" +
+                "    /**\n" +
+                "     * const2 javadoc\n" +
+                "     */\n" +
+                "    ANOTHER_CONSTANT\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void issue234LosingCommentsInArrayInitializerExpr() {
+        CompilationUnit cu = parse("@Anno(stuff={" + EOL +
+                "    // Just," + EOL +
+                "    // an," + EOL +
+                "    // example" + EOL +
+                "})" + EOL +
+                "class ABC {" + EOL +
+                "" + EOL +
+                "}");
+
+        assertEqualsNoEol("@Anno(stuff = {// Just,\n" +
+                "// an,\n" +
+                "// example\n" +
+                "})\n" +
+                "class ABC {\n" +
+                "}\n", cu.toString());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/GeneratedJavaParserTokenManagerTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/GeneratedJavaParserTokenManagerTest.java
new file mode 100644
index 0000000..f990909
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/GeneratedJavaParserTokenManagerTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static com.github.javaparser.StaticJavaParser.parseResource;
+
+class GeneratedJavaParserTokenManagerTest {
+    private String makeFilename(String sampleName) {
+        return "com/github/javaparser/issue_samples/" + sampleName + ".java.txt";
+    }
+
+    @Test
+    void issue1003() throws IOException {
+        parseResource(makeFilename("issue1003"));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/JavaParserTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/JavaParserTest.java
new file mode 100644
index 0000000..86c44c6
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/JavaParserTest.java
@@ -0,0 +1,324 @@
+/*
+ * 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;
+
+import static com.github.javaparser.ParseStart.*;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
+import static com.github.javaparser.Providers.*;
+import static com.github.javaparser.Range.*;
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.utils.CodeGenerationUtils.*;
+import static com.github.javaparser.utils.TestUtils.*;
+import static com.github.javaparser.utils.Utils.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.ArrayCreationExpr;
+import com.github.javaparser.ast.expr.CastExpr;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.LambdaExpr;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ForStmt;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.stmt.SwitchEntry;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.type.IntersectionType;
+import com.github.javaparser.ast.type.Type;
+
+class JavaParserTest {
+
+    @BeforeEach
+    void setToLatestJava() {
+        StaticJavaParser.getConfiguration().setLanguageLevel(BLEEDING_EDGE);
+    }
+
+    @AfterEach
+    void resetJavaLevel() {
+        StaticJavaParser.getConfiguration().setLanguageLevel(CURRENT);
+    }
+
+    @Test
+    void rangeOfAnnotationMemberDeclarationIsCorrect() {
+        String code = "@interface AD { String foo(); }";
+        CompilationUnit cu = parse(code);
+        AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
+        assertTrue(memberDeclaration.getRange().isPresent());
+        assertEquals(new Range(new Position(1, 17), new Position(1, 29)), memberDeclaration.getRange().get());
+    }
+
+    @Test
+    void testSourcePositionsWithUnicodeEscapes() {
+        String code = "@interface AD \\u007B String foo(); \\u007D";
+        CompilationUnit cu = parseWithUnicodeEscapes(code).getResult().get();
+        AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
+        assertTrue(memberDeclaration.getRange().isPresent());
+        assertEquals(new Range(new Position(1, 22), new Position(1, 34)), memberDeclaration.getRange().get());
+    }
+
+    @Test
+    void testSourcePositionsWithBrokenUnicodeEscapes() {
+    	// Source positions
+    	//                      111111111122222222 2 22333 3333
+    	//             123456789012345678901234567 8 90123 4567
+    	String code = "@interface AD { String X = \"\\uABC\"; }";
+    	ParseResult<CompilationUnit> cu = parseWithUnicodeEscapes(code);
+    	assertFalse(cu.getResult().isPresent());
+    	assertEquals("Lexical error at line 1, column 34.  Encountered: \"\\\"\" (34), after : \"\\\"\\\\uABC\"", cu.getProblem(0).getMessage());
+    }
+    
+	private static ParseResult<CompilationUnit> parseWithUnicodeEscapes(String code) {
+		ParserConfiguration config = new ParserConfiguration();
+        config.setPreprocessUnicodeEscapes(true);
+		return new JavaParser(config).parse(code);
+	}
+
+    @Test
+    void rangeOfAnnotationMemberDeclarationWithArrayTypeIsCorrect() {
+        String code = "@interface AD { String[] foo(); }";
+        CompilationUnit cu = parse(code);
+        AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
+        assertTrue(memberDeclaration.getRange().isPresent());
+        assertEquals(new Range(new Position(1, 17), new Position(1, 31)), memberDeclaration.getRange().get());
+    }
+
+    @Test
+    void rangeOfArrayCreationLevelWithExpressionIsCorrect() {
+        String code = "new int[123][456]";
+        ArrayCreationExpr expression = parseExpression(code);
+        Optional<Range> range;
+
+        range = expression.getLevels().get(0).getRange();
+        assertTrue(range.isPresent());
+        assertEquals(new Range(new Position(1, 8), new Position(1, 12)), range.get());
+
+        range = expression.getLevels().get(1).getRange();
+        assertTrue(range.isPresent());
+        assertEquals(new Range(new Position(1, 13), new Position(1, 17)), range.get());
+    }
+
+    @Test
+    void rangeOfArrayCreationLevelWithoutExpressionIsCorrect() {
+        String code = "new int[][]";
+        ArrayCreationExpr expression = parseExpression(code);
+        Optional<Range> range;
+
+        range = expression.getLevels().get(0).getRange();
+        assertTrue(range.isPresent());
+        assertEquals(new Range(new Position(1, 8), new Position(1, 9)), range.get());
+
+        range = expression.getLevels().get(1).getRange();
+        assertTrue(range.isPresent());
+        assertEquals(new Range(new Position(1, 10), new Position(1, 11)), range.get());
+    }
+
+    @Test
+    void parseErrorContainsLocation() {
+        ParseResult<CompilationUnit> result = new JavaParser().parse(COMPILATION_UNIT, provider("class X { // blah"));
+
+        Problem problem = result.getProblem(0);
+        assertEquals(range(1, 9, 1, 17), problem.getLocation().get().toRange().get());
+        assertEquals("Parse error. Found <EOF>, expected one of  \";\" \"<\" \"@\" \"abstract\" \"boolean\" \"byte\" \"char\" \"class\" \"default\" \"double\" \"enum\" \"exports\" \"final\" \"float\" \"int\" \"interface\" \"long\" \"module\" \"native\" \"open\" \"opens\" \"private\" \"protected\" \"provides\" \"public\" \"requires\" \"short\" \"static\" \"strictfp\" \"synchronized\" \"to\" \"transient\" \"transitive\" \"uses\" \"void\" \"volatile\" \"with\" \"{\" \"}\" <IDENTIFIER>", problem.getMessage());
+        assertInstanceOf(ParseException.class, problem.getCause().get());
+    }
+
+    @Test
+    void parseIntersectionType() {
+        String code = "(Runnable & Serializable) (() -> {})";
+        Expression expression = parseExpression(code);
+        Type type = expression.asCastExpr().getType();
+
+        assertTrue(type instanceof IntersectionType);
+        IntersectionType intersectionType = type.asIntersectionType();
+        assertEquals(2, intersectionType.getElements().size());
+        assertTrue(intersectionType.getElements().get(0) instanceof ClassOrInterfaceType);
+        assertEquals("Runnable", intersectionType.getElements().get(0).asClassOrInterfaceType().getNameAsString());
+        assertTrue(intersectionType.getElements().get(1) instanceof ClassOrInterfaceType);
+        assertEquals("Serializable", intersectionType.getElements().get(1).asClassOrInterfaceType().getNameAsString());
+    }
+
+    @Test
+    void rangeOfIntersectionType() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        CompilationUnit cu = parse(code);
+        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
+        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
+        Type type = castExpr.getType();
+        assertEquals(range(3, 13, 3, 54), type.getRange().get());
+    }
+
+    @Test
+    void rangeOfCast() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        CompilationUnit cu = parse(code);
+        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
+        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
+        assertEquals(range(3, 12, 3, 101), castExpr.getRange().get());
+    }
+
+    @Test
+    void rangeOfCastNonIntersection() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>>               )(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        CompilationUnit cu = parse(code);
+        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
+        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
+        assertEquals(range(3, 12, 3, 101), castExpr.getRange().get());
+    }
+
+    @Test
+    void rangeOfLambda() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        CompilationUnit cu = parse(code);
+        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
+        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
+        LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
+        assertEquals(range(3, 56, 3, 101), lambdaExpr.getRange().get());
+        assertEquals(GeneratedJavaParserConstants.LPAREN, lambdaExpr.getTokenRange().get().getBegin().getKind());
+        assertEquals(GeneratedJavaParserConstants.RPAREN, lambdaExpr.getTokenRange().get().getEnd().getKind());
+    }
+
+    @Test
+    void rangeOfLambdaBody() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        CompilationUnit cu = parse(code);
+        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
+        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
+        LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
+        Statement lambdaBody = lambdaExpr.getBody();
+        assertEquals(range(3, 68, 3, 101), lambdaBody.getRange().get());
+    }
+
+    @Test
+    void testNotStoringTokens() {
+        JavaParser javaParser = new JavaParser(new ParserConfiguration().setStoreTokens(false));
+        ParseResult<CompilationUnit> result = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{}"));
+        assertFalse(result.getResult().get().getTokenRange().isPresent());
+    }
+
+    @Test
+    void trailingCodeIsAnError() {
+        assertThrows(ParseProblemException.class, () -> parseBlock("{} efijqoifjqefj"));
+    }
+
+    @Test
+    void trailingWhitespaceIsIgnored() {
+        BlockStmt blockStmt = parseBlock("{} // hello");
+        assertEquals("{}", blockStmt.getTokenRange().get().toString());
+    }
+
+    @Test
+    void everyTokenHasACategory() throws IOException {
+        final int tokenCount = GeneratedJavaParserConstants.tokenImage.length;
+        Path tokenTypesPath = mavenModuleRoot(JavaParserTest.class).resolve("../javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java");
+        CompilationUnit tokenTypesCu = parse(tokenTypesPath);
+        // -1 to take off the default: case.
+        int switchEntries = tokenTypesCu.findAll(SwitchEntry.class).size() - 1;
+        // The amount of "case XXX:" in TokenTypes.java should be equal to the amount of tokens JavaCC knows about:
+        assertEquals(tokenCount, switchEntries);
+    }
+
+    @Test
+    void parsingInitializedAndUnitializedVarsInForStmt() {
+        ForStmt forStmt = parseStatement("for(int a,b=0;;){}").asForStmt();
+        assertEquals(1, forStmt.getInitialization().size());
+        assertTrue(forStmt.getInitialization().get(0).isVariableDeclarationExpr());
+        assertEquals(2, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().size());
+        assertEquals("a", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getNameAsString());
+        assertEquals("b", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getNameAsString());
+        assertFalse(forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getInitializer().isPresent());
+        assertTrue(forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getInitializer().isPresent());
+    }
+
+    @Test
+    void parsingInitializedAndUnitializedVarsInForStmtComplexCase() {
+        // See issue 1281
+        ForStmt forStmt = parseStatement("for(int i, j = array2.length - 1;;){}").asForStmt();
+        assertEquals(1, forStmt.getInitialization().size());
+        assertTrue(forStmt.getInitialization().get(0).isVariableDeclarationExpr());
+        assertEquals(2, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().size());
+        assertEquals("i", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getNameAsString());
+        assertEquals("j", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getNameAsString());
+        assertFalse(forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getInitializer().isPresent());
+        assertTrue(forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getInitializer().isPresent());
+    }
+
+    @Test
+    void creatingNewObjectCreationExprShouldDefaultToParsing() {
+        String className = String.class.getCanonicalName();
+        ClassOrInterfaceType type = parseClassOrInterfaceType(className);
+        ObjectCreationExpr expected = parseExpression("new " + className + "()");
+        ObjectCreationExpr actual = new ObjectCreationExpr(null, type, NodeList.nodeList());
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    void parseModuleDeclaration() {
+        StaticJavaParser.parseModuleDeclaration("module X {}");
+    }
+
+    @Test
+    void parseModuleDirective() {
+        StaticJavaParser.parseModuleDirective("opens C;");
+    }
+
+    @Test
+    void parseTypeParameter() {
+        StaticJavaParser.parseTypeParameter("T extends Serializable & AttachableListener");
+    }
+
+    @Test
+    void parseTypeDeclaration() {
+        StaticJavaParser.parseTypeDeclaration("enum Z {A, B}");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/JavaTokenTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/JavaTokenTest.java
new file mode 100644
index 0000000..288469c
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/JavaTokenTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import com.github.javaparser.ast.expr.Expression;
+import org.junit.jupiter.api.Test;
+
+import java.util.Iterator;
+
+import static com.github.javaparser.GeneratedJavaParserConstants.*;
+import static com.github.javaparser.JavaToken.Category.*;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.Range.range;
+import static org.junit.jupiter.api.Assertions.*;
+
+class JavaTokenTest {
+
+    @Test
+    void testAFewTokens() {
+        ParseResult<Expression> result = new JavaParser().parse(ParseStart.EXPRESSION, provider("1 +/*2*/1 "));
+        Iterator<JavaToken> iterator = result.getResult().get().getTokenRange().get().iterator();
+        assertToken("1", range(1, 1, 1, 1), INTEGER_LITERAL, LITERAL, iterator.next());
+        assertToken(" ", range(1, 2, 1, 2), SPACE, WHITESPACE_NO_EOL, iterator.next());
+        assertToken("+", range(1, 3, 1, 3), PLUS, OPERATOR, iterator.next());
+        assertToken("/*2*/", range(1, 4, 1, 8), MULTI_LINE_COMMENT, COMMENT, iterator.next());
+        assertToken("1", range(1, 9, 1, 9), INTEGER_LITERAL, LITERAL, iterator.next());
+        assertToken(" ", range(1, 10, 1, 10), SPACE, WHITESPACE_NO_EOL, iterator.next());
+        assertToken("", range(1, 10, 1, 10), EOF, WHITESPACE_NO_EOL, iterator.next());
+        assertFalse(iterator.hasNext());
+    }
+
+    private void assertToken(String image, Range range, int kind, JavaToken.Category category, JavaToken token) {
+        assertEquals(image, token.getText());
+        assertEquals(range, token.getRange().get());
+        assertEquals(kind, token.getKind());
+        assertEquals(category, token.getCategory());
+        token.getNextToken().ifPresent(nt -> assertEquals(token, nt.getPreviousToken().get()));
+        token.getPreviousToken().ifPresent(pt -> assertEquals(token, pt.getNextToken().get()));
+        assertTrue(token.getNextToken().isPresent() || token.getPreviousToken().isPresent());
+    }
+
+    @Test
+    void testAFewImagesForTokenKinds() {
+        assertEquals("=", new JavaToken(ASSIGN).getText());
+        // TODO this shouldn't be a space.
+        assertEquals(" ", new JavaToken(EOF).getText());
+        assertEquals("*/", new JavaToken(JAVADOC_COMMENT).getText());
+    }
+
+    @Test
+    void testKindEnum() {
+        JavaToken.Kind kind = JavaToken.Kind.valueOf(GeneratedJavaParserConstants.ASSERT);
+
+        assertEquals(JavaToken.Kind.ASSERT, kind);
+        assertEquals(GeneratedJavaParserConstants.ASSERT, kind.getKind());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/JavadocParserTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/JavadocParserTest.java
new file mode 100644
index 0000000..14a875b
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/JavadocParserTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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;
+
+import com.github.javaparser.javadoc.Javadoc;
+import com.github.javaparser.javadoc.JavadocBlockTag;
+import com.github.javaparser.javadoc.description.JavadocDescription;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class JavadocParserTest {
+
+    @Test
+    void parseSimplestContent() {
+        Assertions.assertEquals(new Javadoc(JavadocDescription.parseText("A simple line of text")),
+                JavadocParser.parse("A simple line of text"));
+    }
+
+    @Test
+    void parseSingleLineWithSpacing() {
+        assertEquals(new Javadoc(JavadocDescription.parseText("The line number of the first character of this Token.")),
+                JavadocParser.parse(" The line number of the first character of this Token. "));
+    }
+
+    @Test
+    void parseSingleLineWithNewLines() {
+        assertEquals(new Javadoc(JavadocDescription.parseText("The string image of the token.")),
+                JavadocParser.parse(EOL +
+                        "   * The string image of the token." + EOL +
+                        "   "));
+    }
+
+    @Test
+    void parseCommentWithNewLines() {
+        String text = EOL +
+                "   * The version identifier for this Serializable class." + EOL +
+                "   * Increment only if the <i>serialized</i> form of the" + EOL +
+                "   * class changes." + EOL +
+                "   ";
+        assertEquals(new Javadoc(JavadocDescription.parseText("The version identifier for this Serializable class." + EOL +
+                        "Increment only if the <i>serialized</i> form of the" + EOL +
+                        "class changes.")),
+                JavadocParser.parse(text));
+    }
+
+    @Test
+    void parseCommentWithIndentation() {
+        String text = "Returns a new Token object, by default." + EOL +
+                "   * However, if you want, you can create and return subclass objects based on the value of ofKind." + EOL +
+                "   *" + EOL +
+                "   *    case MyParserConstants.ID : return new IDToken(ofKind, image);" + EOL +
+                "   *" + EOL +
+                "   * to the following switch statement. Then you can cast matchedToken";
+        assertEquals(new Javadoc(JavadocDescription.parseText("Returns a new Token object, by default." + EOL +
+                        "However, if you want, you can create and return subclass objects based on the value of ofKind." + EOL +
+                        EOL +
+                        "   case MyParserConstants.ID : return new IDToken(ofKind, image);" + EOL +
+                        EOL +
+                        "to the following switch statement. Then you can cast matchedToken")),
+                JavadocParser.parse(text));
+    }
+
+    @Test
+    void parseBlockTagsAndEmptyDescription() {
+        String text = EOL +
+                "   * @deprecated" + EOL +
+                "   * @see #getEndColumn" + EOL +
+                "   ";
+        assertEquals(new Javadoc(JavadocDescription.parseText(""))
+                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.DEPRECATED, ""))
+                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.SEE, "#getEndColumn")), JavadocParser.parse(text));
+    }
+
+    @Test
+    void parseBlockTagsAndProvideTagName() {
+        String expectedText = EOL +
+                "   * @unofficial" + EOL + " " +
+                "   ";
+
+        Javadoc underTest = new Javadoc(JavadocDescription.parseText(""))
+                .addBlockTag(new JavadocBlockTag("unofficial", ""));
+
+
+        assertEquals(underTest, JavadocParser.parse(expectedText));
+        assertEquals(1, underTest.getBlockTags().size());
+        assertEquals("unofficial", underTest.getBlockTags().get(0).getTagName());
+    }
+
+    @Test
+    void parseParamBlockTags() {
+        String text = EOL +
+                "     * Add a field to this and automatically add the import of the type if needed" + EOL +
+                "     *" + EOL +
+                "     * @param typeClass the type of the field" + EOL +
+                "     *       @param name the name of the field" + EOL +
+                "     * @param modifiers the modifiers like {@link Modifier#PUBLIC}" + EOL +
+                "     * @return the {@link FieldDeclaration} created" + EOL +
+                "     ";
+        Javadoc res = JavadocParser.parse(text);
+        assertEquals(new Javadoc(JavadocDescription.parseText("Add a field to this and automatically add the import of the type if needed"))
+                .addBlockTag(JavadocBlockTag.createParamBlockTag("typeClass", "the type of the field"))
+                .addBlockTag(JavadocBlockTag.createParamBlockTag("name", "the name of the field"))
+                .addBlockTag(JavadocBlockTag.createParamBlockTag("modifiers", "the modifiers like {@link Modifier#PUBLIC}"))
+                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.RETURN, "the {@link FieldDeclaration} created")), res);
+    }
+
+    @Test
+    void parseMultilineParamBlockTags() {
+        String text = EOL +
+                "     * Add a field to this and automatically add the import of the type if needed" + EOL +
+                "     *" + EOL +
+                "     * @param typeClass the type of the field" + EOL +
+                "     *     continued in a second line" + EOL +
+                "     * @param name the name of the field" + EOL +
+                "     * @param modifiers the modifiers like {@link Modifier#PUBLIC}" + EOL +
+                "     * @return the {@link FieldDeclaration} created" + EOL +
+                "     ";
+        Javadoc res = JavadocParser.parse(text);
+        assertEquals(new Javadoc(JavadocDescription.parseText("Add a field to this and automatically add the import of the type if needed"))
+                .addBlockTag(JavadocBlockTag.createParamBlockTag("typeClass", "the type of the field" + EOL + "    continued in a second line"))
+                .addBlockTag(JavadocBlockTag.createParamBlockTag("name", "the name of the field"))
+                .addBlockTag(JavadocBlockTag.createParamBlockTag("modifiers", "the modifiers like {@link Modifier#PUBLIC}"))
+                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.RETURN, "the {@link FieldDeclaration} created")), res);
+    }
+
+    @Test
+    void startsWithAsteriskEmpty() {
+        assertEquals(-1, JavadocParser.startsWithAsterisk(""));
+    }
+
+    @Test
+    void startsWithAsteriskNoAsterisk() {
+        assertEquals(-1, JavadocParser.startsWithAsterisk(" ciao"));
+    }
+
+    @Test
+    void startsWithAsteriskAtTheBeginning() {
+        assertEquals(0, JavadocParser.startsWithAsterisk("* ciao"));
+    }
+
+    @Test
+    void startsWithAsteriskAfterSpaces() {
+        assertEquals(3, JavadocParser.startsWithAsterisk("   * ciao"));
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ParseErrorRecoveryTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ParseErrorRecoveryTest.java
new file mode 100644
index 0000000..839ad92
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ParseErrorRecoveryTest.java
@@ -0,0 +1,42 @@
+package com.github.javaparser;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.stmt.LabeledStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ParseErrorRecoveryTest {
+    private final JavaParser parser = new JavaParser();
+
+    @Test
+    void compilationUnitRecovery() {
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, provider("XXX")).getResult().get();
+        assertEquals(UNPARSABLE, cu.getParsed());
+    }
+
+    @Test
+    void bodystatementSemicolonRecovery() {
+        MethodDeclaration cu = parser.parse(ParseStart.CLASS_BODY, provider("int x(){X X X;}")).getResult().get().asMethodDeclaration();
+        Statement xxx = cu.getBody().get().getStatements().get(0);
+        assertEquals(UNPARSABLE, xxx.getParsed());
+    }
+
+    @Test
+    void bodystatementClosingBraceRecovery() {
+        MethodDeclaration cu = parser.parse(ParseStart.CLASS_BODY, provider("int x(){X X X}")).getResult().get().asMethodDeclaration();
+        Statement xxx = cu.getBody().get();
+        assertEquals(UNPARSABLE, xxx.getParsed());
+    }
+
+    @Test
+    void labeledStatementSemicolonRecovery() {
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, provider("class X{int x(){aaa:X X X;}}")).getResult().get();
+        LabeledStmt xxx = cu.getClassByName("X").get().getMethods().get(0).getBody().get().getStatements().get(0).asLabeledStmt();
+        assertEquals(UNPARSABLE, xxx.getStatement().getParsed());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java
new file mode 100644
index 0000000..e1c0ac1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java
@@ -0,0 +1,33 @@
+package com.github.javaparser;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.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.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class ParserConfigurationTest {
+    @Test
+    void storeNoTokens() {
+        ParseResult<CompilationUnit> result = new JavaParser(new ParserConfiguration().setStoreTokens(false)).parse(ParseStart.COMPILATION_UNIT, provider("class X{}"));
+
+        assertFalse(result.getResult().get().getTokenRange().isPresent());
+        assertTrue(result.getResult().get().findAll(Node.class).stream().noneMatch(node -> node.getTokenRange().isPresent()));
+    }
+
+    @Test
+    void noProblemsHere() {
+        ParseResult<Statement> result =
+                new JavaParser(new ParserConfiguration().setLanguageLevel(RAW))
+                        .parse(STATEMENT, provider("try{}"));
+        assertTrue(result.isSuccessful());
+    }
+
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/PositionMappingTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/PositionMappingTest.java
new file mode 100644
index 0000000..dd56484
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/PositionMappingTest.java
@@ -0,0 +1,164 @@
+/*

+ * 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;

+

+import static com.github.javaparser.UnicodeEscapeProcessingProviderTest.*;

+import static org.junit.jupiter.api.Assertions.*;

+

+import java.io.IOException;

+import java.util.Arrays;

+import java.util.Iterator;

+import java.util.List;

+

+import org.junit.jupiter.api.Test;

+

+import com.github.javaparser.UnicodeEscapeProcessingProvider.PositionMapping;

+

+/**

+ * Test case for {@link PositionMapping}.

+ *

+ * @author <a href="mailto:bhu@top-logic.com">Bernhard Haumacher</a>

+ */

+@SuppressWarnings("javadoc")

+public class PositionMappingTest {

+

+	@Test

+	public void testNoMapping() throws IOException {

+		List<List<String>> input = lines(

+			line("Hello World !\n"), 

+			line("Next Line\r"), 

+			line("Third Line\r\n"), 

+			line("Fourth Line."));

+		String inputText = text(input);

+		UnicodeEscapeProcessingProvider provider = provider(inputText);

+		String outputText = process(provider);

+		assertEquals(inputText, outputText);

+		PositionMapping mapping = provider.getPositionMapping();

+		assertTrue(mapping.isEmpty());

+		assertEquals(4, provider.getInputCounter().getLine());

+		assertEquals(4, provider.getOutputCounter().getLine());

+		assertSame(PositionMapping.PositionUpdate.NONE, mapping.lookup(new Position(10000, 1)));

+	}

+

+	@Test

+	public void testEncodedLineFeed() throws IOException {

+		List<List<String>> input = lines(

+			line("B", "\\u000A", "C"));

+		List<List<String>> output = lines(

+			line("B", "\n"), 

+			line("C"));

+		

+		checkConvert(input, output);

+	}

+	

+	@Test

+	public void testComplexMapping() throws IOException {

+		List<List<String>> input = lines(

+			// Character positions:

+			//                      111    1 11111    1222    2 2222     2

+			//    1    2 34567    89012    3 45678    9012    3 45678    9

+			line("H", "\\u00E4", "llo W", "\\u00F6", "rld!", "\\u000A", "123 N", "\\u00E4", "xt Line", "\\u000D", "Third Line", "\r\n"), 

+			line("Fo", "\\u00FC", "rth Line."));

+		List<List<String>> output = lines(

+			line("H", "ä", "llo W", "ö", "rld!", "\n"), 

+			line("123 N", "ä", "xt Line", "\r"), 

+			line("Third Line", "\r\n"), 

+			line("Fo", "ü", "rth Line."));

+

+		checkConvert(input, output);

+	}

+

+	private void checkConvert(List<List<String>> input,

+			List<List<String>> output) throws IOException {

+		UnicodeEscapeProcessingProvider provider = provider(text(input));

+		String decoded = process(provider);

+		assertEquals(text(output), decoded);

+		

+		PositionMapping mapping = provider.getPositionMapping();

+		

+		// Coarse grained test.

+		assertEquals(input.size(), provider.getInputCounter().getLine());

+		assertEquals(output.size(), provider.getOutputCounter().getLine());

+		

+		// Fine grained test.

+		int inPosLine = 1;

+		int inPosColumn = 1;

+		int outPosLine = 1;

+		int outPosColumn = 1;

+		Iterator<List<String>> outLineIt = output.iterator();

+		List<String> outLine = outLineIt.next();

+		Iterator<String> outPartIt = outLine.iterator();

+		String outPart = outPartIt.next();

+		boolean outFinished = false;

+		for (List<String> inLine : input) {

+			for (String inPart : inLine) {

+				assertFalse(outFinished);

+				

+				Position inPos = new Position(inPosLine, inPosColumn);

+				Position outPos = new Position(outPosLine, outPosColumn);

+				Position transfomedOutPos = mapping.transform(outPos);

+

+				assertEquals(inPos, transfomedOutPos, 

+					"Position mismatch at '" + outPart + "' " + outPos + " -> '" + inPart + "' " + inPos + ".");

+

+				outPosColumn += outPart.length();

+				inPosColumn += inPart.length();

+				

+				if (!outPartIt.hasNext()) {

+					if (outLineIt.hasNext()) {

+						outPartIt = outLineIt.next().iterator();

+						outPosLine ++;

+						outPosColumn = 1;

+

+						outPart = outPartIt.next();

+					} else {

+						outFinished = true;

+					}

+				} else {

+					outPart = outPartIt.next();

+				}

+			}

+			

+			inPosColumn = 1;

+			inPosLine++;

+		}

+	}

+	

+	private static String text(List<List<String>> input) {

+		StringBuilder result = new StringBuilder();

+		for (List<String> line : input) {

+			for (String part : line) {

+				result.append(part);

+			}

+		}

+		return result.toString();

+	}

+

+	@SafeVarargs

+	private static List<String> line(String ...parts) {

+		return Arrays.asList(parts);

+	}

+

+	@SafeVarargs

+	private static List<List<String>> lines(List<String> ...lines) {

+		return Arrays.asList(lines);

+	}

+	

+}

diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ProblemTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ProblemTest.java
new file mode 100644
index 0000000..e7a2617
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ProblemTest.java
@@ -0,0 +1,31 @@
+package com.github.javaparser;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ProblemTest {
+    @Test
+    void testSimpleGetters() {
+        Problem problem = new Problem("Parse error", TokenRange.INVALID, new Exception());
+
+        assertEquals(TokenRange.INVALID, problem.getLocation().get());
+        assertEquals("Parse error", problem.getMessage());
+        assertInstanceOf(Exception.class, problem.getCause().get());
+    }
+
+    @Test
+    void testVerboseMessage() {
+        Problem problem = new Problem("Parse error", TokenRange.INVALID, null);
+
+        assertEquals("(line ?,col ?) Parse error", problem.getVerboseMessage());
+    }
+
+    @Test
+    void testVerboseMessageWithoutLocation() {
+        Problem problem = new Problem("Parse error", null, null);
+
+        assertEquals("Parse error", problem.getVerboseMessage());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ProvidersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ProvidersTest.java
new file mode 100644
index 0000000..82ad6d1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ProvidersTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ProvidersTest {
+
+    @Test
+    void testResourceProvider() throws IOException {
+        Provider provider = Providers.resourceProvider("com/github/javaparser/issue_samples/Issue290.java.txt");
+        assertNotNull(provider);
+        JavaParser parser = new JavaParser();
+        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
+        assertTrue(parse.isSuccessful());
+    }
+
+    @Test
+    void testResourceProviderWithWrongEncoding() throws IOException {
+        Provider provider = Providers.resourceProvider("com/github/javaparser/TestFileIso88591.java");
+        assertNotNull(provider);
+        JavaParser parser = new JavaParser();
+        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
+        assertFalse(parse.isSuccessful());
+    }
+
+    @Test
+    void testResourceProviderWithEncoding() throws IOException {
+        Provider provider = Providers.resourceProvider(
+                "com/github/javaparser/TestFileIso88591.java",
+                Charset.forName("ISO-8859-1")
+        );
+        assertNotNull(provider);
+        JavaParser parser = new JavaParser();
+        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
+        assertTrue(parse.isSuccessful());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/RangeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/RangeTest.java
new file mode 100644
index 0000000..1077c9b
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/RangeTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class RangeTest {
+
+    @Test
+    void aRangeContainsItself() {
+        Range r = Range.range(1, 1, 3, 10);
+        assertTrue(r.contains(r));
+    }
+
+    @Test
+    void aRangeDoesNotStrictlyContainsItself() {
+        Range r = Range.range(1, 1, 3, 10);
+        assertFalse(r.strictlyContains(r));
+    }
+
+    @Test
+    void overlappingButNotContainedRangesAreNotOnContains() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(2, 1, 7, 10);
+        assertFalse(r1.contains(r2));
+        assertFalse(r2.contains(r1));
+    }
+
+    @Test
+    void overlappingButNotContainedRangesAreNotOnStrictlyContains() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(2, 1, 7, 10);
+        assertFalse(r1.strictlyContains(r2));
+        assertFalse(r2.strictlyContains(r1));
+    }
+
+    @Test
+    void unrelatedRangesAreNotOnContains() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(5, 1, 7, 10);
+        assertFalse(r1.contains(r2));
+        assertFalse(r2.contains(r1));
+    }
+
+    @Test
+    void unrelatedRangesAreNotOnStrictlyContains() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(5, 1, 7, 10);
+        assertFalse(r1.strictlyContains(r2));
+        assertFalse(r2.strictlyContains(r1));
+    }
+
+    @Test
+    void strictlyContainedRangesOnContains() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(2, 1, 3, 4);
+        assertTrue(r1.contains(r2));
+        assertFalse(r2.contains(r1));
+    }
+
+    @Test
+    void strictlyContainedRangesOnStrictlyContains() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(2, 1, 3, 4);
+        assertTrue(r1.strictlyContains(r2));
+        assertFalse(r2.strictlyContains(r1));
+    }
+
+    @Test
+    void containsConsiderLines() {
+        Range r1 = Range.range(22, 9, 22, 29);
+        Range r2 = Range.range(26, 19, 26, 28);
+        assertFalse(r1.contains(r2));
+        assertFalse(r2.contains(r1));
+    }
+
+    @Test
+    void lineCountIsReturned() {
+        Range r1 = Range.range(1, 1, 5, 2);
+        Range r2 = Range.range(26, 5, 57, 6);
+        assertEquals(5, r1.getLineCount());
+        assertEquals(32, r2.getLineCount());
+    }
+    
+    @Test
+    void aRangeContainsItsBegin() {
+        Range r = Range.range(1, 1, 3, 10);
+        assertTrue(r.contains(r.begin));
+    }
+
+    @Test
+    void aRangeContainsItsEnd() {
+        Range r = Range.range(1, 1, 3, 10);
+        assertTrue(r.contains(r.end));
+    }
+    
+    @Test
+    void aRangeDoesntStrictlyContainItsBegin() {
+        Range r = Range.range(1, 1, 3, 10);
+        assertFalse(r.strictlyContains(r.begin));
+    }
+
+    @Test
+    void aRangeDoesntStrictlyContainItsEnd() {
+        Range r = Range.range(1, 1, 3, 10);
+        assertFalse(r.strictlyContains(r.end));
+    }
+    
+    @Test
+    void rangesOverlap() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(3, 5, 5, 10);
+        assertTrue(r1.overlapsWith(r2));
+        assertTrue(r2.overlapsWith(r1));
+    }
+    
+    @Test
+    void rangesDoNotOverlap() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(4, 11, 5, 10);
+        assertFalse(r1.overlapsWith(r2));
+        assertFalse(r2.overlapsWith(r1));
+    }
+    
+    @Test
+    void strictlyContainedRangesOverlap() {
+        Range r1 = Range.range(1, 1, 3, 10);
+        Range r2 = Range.range(2, 1, 3, 4);
+        assertTrue(r1.overlapsWith(r2));
+        assertTrue(r2.overlapsWith(r1));
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/TokenRangeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/TokenRangeTest.java
new file mode 100644
index 0000000..0c70fc6
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/TokenRangeTest.java
@@ -0,0 +1,51 @@
+package com.github.javaparser;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.*;
+
+class TokenRangeTest {
+    @Test
+    void toStringWorks() {
+        CompilationUnit cu = parse("class X {\n\tX(){\n// hello\n}\n}");
+        assertEquals("X(){\n// hello\n}", cu.getClassByName("X").get().getDefaultConstructor().get().getTokenRange().get().toString());
+    }
+
+    @Test
+    void renumberRangesWorks() {
+        CompilationUnit cu = parse("class X {\n\tX(){\n// hello\n}\n}");
+
+        assertEquals("1,1-5/6,1-1/7,1-1/8,1-1/9,1-1/10,1-1/1,2-1/2,2-1/3,2-1/4,2-1/5,2-1/6,2-1/1,3-8/9,3-1/1,4-1/2,4-1/1,5-1/1,5-1/", makeRangesString(cu));
+
+        TokenRange tokenRange = cu.getTokenRange().get();
+        tokenRange.getBegin().insertAfter(new JavaToken(1, "feif"));
+        tokenRange.getBegin().getNextToken().get().getNextToken().get().insert(new JavaToken(JavaToken.Kind.WINDOWS_EOL.getKind(), "\r\n"));
+        cu.recalculatePositions();
+
+        assertEquals("1,1-5/6,1-4/10,1-2/1,2-1/2,2-1/3,2-1/4,2-1/5,2-1/1,3-1/2,3-1/3,3-1/4,3-1/5,3-1/6,3-1/1,4-8/9,4-1/1,5-1/2,5-1/1,6-1/2,6-1/", makeRangesString(cu));
+    }
+
+    /**
+     * Make a compact String for comparing token range positions.
+     */
+    private String makeRangesString(Node node) {
+        Optional<JavaToken> token = node.getTokenRange().map(TokenRange::getBegin);
+        StringBuilder result = new StringBuilder();
+        while (token.isPresent()) {
+            token = token.flatMap(t -> {
+                result.append(t.getRange().map(r ->
+                        r.begin.column + "," + r.begin.line + "-" +
+                                (r.end.column - r.begin.column + 1) + "/"
+
+                ).orElse("?"));
+                return t.getNextToken();
+            });
+        }
+        return result.toString();
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/UnicodeEscapeProcessingProviderTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/UnicodeEscapeProcessingProviderTest.java
new file mode 100644
index 0000000..b91ec51
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/UnicodeEscapeProcessingProviderTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 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;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test case for {@link UnicodeEscapeProcessingProvider}.
+ */
+public class UnicodeEscapeProcessingProviderTest {
+
+	@Test
+	void testUnicodeEscape() throws IOException {
+		assertEquals("13" + '\u12aA' + "98", new String(read("13\\u12aA98")));
+	}
+
+	@Test
+	void testEscapedUnicodeEscape() throws IOException {
+		assertEquals("13\\\\u12aA98", new String(read("13\\\\u12aA98")));
+	}
+	
+	@Test
+	void testUnicodeEscapeWithMultipleUs() throws IOException {
+		assertEquals("13" + '\u12aA' + "98", new String(read("13\\uuuuuu12aA98")));
+	}
+	
+	@Test
+	void testInputEndingInBackslash() throws IOException {
+		assertEquals("foobar\\", new String(read("foobar\\")));
+	}
+	
+	@Test
+	void testInputEndingInBackslashU() throws IOException {
+		assertEquals("foobar\\u", new String(read("foobar\\u")));
+	}
+	
+	@Test
+	void testInputEndingInBackslashUs() throws IOException {
+		assertEquals("foobar\\uuuuuu", new String(read("foobar\\uuuuuu")));
+	}
+	
+	@Test
+	void testInputEndingInBackslashU1() throws IOException {
+		assertEquals("foobar\\uA", new String(read("foobar\\uA")));
+	}
+	
+	@Test
+	void testInputEndingInBackslashU2() throws IOException {
+		assertEquals("foobar\\uAB", new String(read("foobar\\uAB")));
+	}
+	
+	@Test
+	void testInputEndingInBackslashU3() throws IOException {
+		assertEquals("foobar\\uABC", new String(read("foobar\\uABC")));
+	}
+	
+	@Test
+	void testInputEndingUnicodeEscape() throws IOException {
+		assertEquals("foobar\uABCD", new String(read("foobar\\uABCD")));
+	}
+	
+	@Test
+	void testEmptyInput() throws IOException {
+		assertEquals("", new String(read("")));
+	}
+
+	@Test
+	void testBadUnicodeEscape0() throws IOException {
+		assertEquals("13\\ux", new String(read("13\\ux")));
+	}
+	
+	@Test
+	void testBadUnicodeEscape1() throws IOException {
+		assertEquals("13\\u1x", new String(read("13\\u1x")));
+	}
+
+	@Test
+	void testBadUnicodeEscape2() throws IOException {
+		assertEquals("13\\u1Ax", new String(read("13\\u1Ax")));
+	}
+
+	@Test
+	void testBadUnicodeEscape3() throws IOException {
+		assertEquals("13\\u1ABx", new String(read("13\\u1ABx")));
+	}
+
+	@Test
+	void testBadUnicodeEscapeMultipleUs() throws IOException {
+		assertEquals("13\\uuuuuu1ABx", new String(read("13\\uuuuuu1ABx")));
+	}
+
+	@Test
+	void testPushBackWithFullBuffer() throws IOException {
+		assertEquals("12345678\\uuxxxxxxxxxxxxxxxxxxxxxxx", new String(read("12345678\\uuxxxxxxxxxxxxxxxxxxxxxxx")));
+	}
+	
+	@Test
+	void testPushBackWithBufferShift() throws IOException {
+		assertEquals("12345678\\uuxx", new String(read("12345678\\uuxx")));
+	}
+	
+	static String read(String source) throws IOException {
+		return process(provider(source));
+	}
+
+	static UnicodeEscapeProcessingProvider provider(String source) {
+		UnicodeEscapeProcessingProvider provider = new UnicodeEscapeProcessingProvider(10, 
+				new StringProvider(source));
+		return provider;
+	}
+
+	static String process(UnicodeEscapeProcessingProvider provider)
+			throws IOException {
+		StringBuilder result = new StringBuilder();
+		char[] buffer = new char[10];
+		while (true) {
+			int direct = provider.read(buffer, 0, buffer.length);
+			if (direct < 0) {
+				break;
+			}
+			result.append(buffer, 0, direct);
+		}
+		
+		provider.close();
+	
+		return result.toString();
+	}
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/AncestorDescendantTests.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/AncestorDescendantTests.java
new file mode 100644
index 0000000..9ac304b
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/AncestorDescendantTests.java
@@ -0,0 +1,108 @@
+package com.github.javaparser.ast;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class AncestorDescendantTests {
+
+    @Test
+    void nodeIsNotAncestorOfItself() throws IOException {
+        JavaParser parser = new JavaParser();
+
+        Provider provider = Providers.resourceProvider("com/github/javaparser/range/A.java");
+        assertNotNull(provider);
+        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
+        assertTrue(parse.isSuccessful());
+
+        VariableDeclarationExpr node = parse.getResult().get()
+                .getType(0) // class A
+                .getMember(0).asMethodDeclaration() // method foo()
+                .getBody().get().getStatement(0).asExpressionStmt() // int a = 42;
+                .getExpression().asVariableDeclarationExpr(); // a = 42
+
+        assertFalse(node.isAncestorOf(node));
+    }
+
+    @Test
+    void nodeIsNotDescendantOfItself() throws IOException {
+        JavaParser parser = new JavaParser();
+
+        Provider provider = Providers.resourceProvider("com/github/javaparser/range/A.java");
+        assertNotNull(provider);
+        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
+        assertTrue(parse.isSuccessful());
+
+        VariableDeclarationExpr node = parse.getResult().get()
+                .getType(0) // class A
+                .getMember(0).asMethodDeclaration() // method foo()
+                .getBody().get().getStatement(0).asExpressionStmt() // int a = 42;
+                .getExpression().asVariableDeclarationExpr(); // a = 42
+
+        assertFalse(node.isDescendantOf(node));
+    }
+
+    @Test
+    void nodeInSameFileIsDescendantOfAncestor() throws IOException {
+        JavaParser parser = new JavaParser();
+
+        Provider provider = Providers.resourceProvider("com/github/javaparser/range/A.java");
+        assertNotNull(provider);
+        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
+        assertTrue(parse.isSuccessful());
+
+        VariableDeclarationExpr superNode = parse.getResult().get()
+                .getType(0) // class A
+                .getMember(0).asMethodDeclaration() // method foo()
+                .getBody().get().getStatement(0).asExpressionStmt() // int a = 42;
+                .getExpression().asVariableDeclarationExpr(); // a = 42
+
+        Expression subNode = superNode.getVariable(0).getInitializer().get(); // 42
+
+        assertTrue(superNode.isAncestorOf(subNode));
+        assertFalse(subNode.isAncestorOf(superNode));
+        assertTrue(subNode.isDescendantOf(superNode));
+        assertFalse(superNode.isDescendantOf(subNode));
+    }
+
+    @Test
+    void nodesInTwoDifferentFilesAreNotDescendantOrAncestorOfEachOther() throws IOException {
+        JavaParser parser = new JavaParser();
+
+        Provider providerA = Providers.resourceProvider("com/github/javaparser/range/A.java");
+        assertNotNull(providerA);
+        ParseResult<CompilationUnit> parseA = parser.parse(ParseStart.COMPILATION_UNIT, providerA);
+        assertTrue(parseA.isSuccessful());
+
+        Provider providerB = Providers.resourceProvider("com/github/javaparser/range/B.java");
+        assertNotNull(providerB);
+        ParseResult<CompilationUnit> parseB = parser.parse(ParseStart.COMPILATION_UNIT, providerB);
+        assertTrue(parseB.isSuccessful());
+
+        VariableDeclarationExpr superNodeA = parseA.getResult().get()
+                .getType(0) // class A
+                .getMember(0).asMethodDeclaration() // method foo()
+                .getBody().get().getStatement(0).asExpressionStmt() // int a = 42;
+                .getExpression().asVariableDeclarationExpr(); // a = 42
+
+        Expression subNodeA = superNodeA.getVariable(0).getInitializer().get(); // 42
+
+        VariableDeclarationExpr superNodeB = parseB.getResult().get()
+                .getType(0) // class B
+                .getMember(0).asMethodDeclaration() // method foo()
+                .getBody().get().getStatement(0).asExpressionStmt() // int b = 42;
+                .getExpression().asVariableDeclarationExpr(); // b = 42
+
+        Expression subNodeB = superNodeB.getVariable(0).getInitializer().get(); // 42
+
+        assertFalse(superNodeA.isAncestorOf(superNodeB));
+        assertFalse(superNodeA.isDescendantOf(subNodeB));
+        assertFalse(superNodeB.isAncestorOf(superNodeA));
+        assertFalse(superNodeB.isDescendantOf(subNodeA));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/CompilationUnitTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/CompilationUnitTest.java
new file mode 100644
index 0000000..7ba1298
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/CompilationUnitTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.utils.CodeGenerationUtils.mavenModuleRoot;
+import static org.junit.jupiter.api.Assertions.*;
+
+class CompilationUnitTest {
+    @Test
+    void issue578TheFirstCommentIsWithinTheCompilationUnit() {
+        CompilationUnit compilationUnit = parse("// This is my class, with my comment\n" +
+                "class A {\n" +
+                "    static int a;\n" +
+                "}");
+
+        assertEquals(1, compilationUnit.getAllContainedComments().size());
+    }
+
+    @Test
+    void testGetSourceRoot() throws IOException {
+        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
+        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "Z.java"));
+
+        CompilationUnit cu = parse(testFile);
+        Path sourceRoot1 = cu.getStorage().get().getSourceRoot();
+        assertEquals(sourceRoot, sourceRoot1);
+    }
+
+    @Test
+    void testGetSourceRootWithBadPackageDeclaration() {
+        assertThrows(RuntimeException.class, () -> {
+            Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
+        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "A.java"));
+        CompilationUnit cu = parse(testFile);
+        cu.getStorage().get().getSourceRoot();
+    });
+        
+        }
+
+    @Test
+    void testGetSourceRootInDefaultPackage() throws IOException {
+        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources", "com", "github", "javaparser", "storage")).normalize();
+        Path testFile = sourceRoot.resolve(Paths.get("B.java"));
+
+        CompilationUnit cu = parse(testFile);
+        Path sourceRoot1 = cu.getStorage().get().getSourceRoot();
+        assertEquals(sourceRoot, sourceRoot1);
+    }
+    
+    @Test
+    void testGetPrimaryTypeName() throws IOException {
+        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
+        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "PrimaryType.java"));
+        CompilationUnit cu = parse(testFile);
+        
+        assertEquals("PrimaryType", cu.getPrimaryTypeName().get());
+    }
+
+    @Test
+    void testNoPrimaryTypeName() {
+        CompilationUnit cu = parse("class PrimaryType{}");
+
+        assertFalse(cu.getPrimaryTypeName().isPresent());
+    }
+    @Test
+    void testGetPrimaryType() throws IOException {
+        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
+        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "PrimaryType.java"));
+        CompilationUnit cu = parse(testFile);
+
+        assertEquals("PrimaryType",     cu.getPrimaryType().get().getNameAsString());
+    }
+
+    @Test
+    void testNoPrimaryType() throws IOException {
+        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
+        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "PrimaryType2.java"));
+        CompilationUnit cu = parse(testFile);
+
+        assertFalse(cu.getPrimaryType().isPresent());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/DataKeyTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/DataKeyTest.java
new file mode 100644
index 0000000..cf54cf6
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/DataKeyTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.expr.SimpleName;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class DataKeyTest {
+    private static final DataKey<String> ABC = new DataKey<String>() {
+    };
+    private static final DataKey<String> DEF = new DataKey<String>() {
+    };
+    private static final DataKey<List<String>> LISTY = new DataKey<List<String>>() {
+    };
+    private static final DataKey<List<String>> DING = new DataKey<List<String>>() {
+    };
+
+    @Test
+    void addAFewKeysAndSeeIfTheyAreStoredCorrectly() {
+        Node node = new SimpleName();
+
+        node.setData(ABC, "Hurray!");
+        node.setData(LISTY, Arrays.asList("a", "b"));
+        node.setData(ABC, "w00t");
+
+        assertThat(node.getData(ABC)).contains("w00t");
+        assertThat(node.getData(LISTY)).containsExactly("a", "b");
+        assertThat(node.containsData(ABC)).isTrue();
+        assertThat(node.containsData(LISTY)).isTrue();
+        assertThat(node.containsData(DING)).isFalse();
+    }
+
+    @Test
+    void aNonExistentKeyThrowsAnException() {
+        Node node = new SimpleName();
+
+        assertThrows(IllegalStateException.class, () -> node.getData(DING));
+    }
+
+    @Test
+    void cloningCopiesData() {
+        Node node = new SimpleName();
+        node.setData(ABC, "ABC!");
+        node.setData(DEF, "DEF!");
+
+        Node clone = node.clone();
+        assertEquals("ABC!", clone.getData(ABC));
+        assertEquals("DEF!", clone.getData(DEF));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/FindNodeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/FindNodeTest.java
new file mode 100644
index 0000000..bf57810
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/FindNodeTest.java
@@ -0,0 +1,83 @@
+package com.github.javaparser.ast;
+
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.TryStmt;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Some tests for finding descendant and ancestor nodes.
+ */
+class FindNodeTest {
+    @Test
+    void testFindFirst() {
+        CompilationUnit cu = parse(
+                "class Foo {\n" +
+                        "    void foo() {\n" +
+                        "        try {\n" +
+                        "        } catch (Exception e) {\n" +
+                        "        } finally {\n" +
+                        "            try {\n" +
+                        "            } catch (Exception e) {\n" +
+                        "                foo();\n" +
+                        "            } finally {\n" +
+                        "            }\n" +
+                        "        }\n" +
+                        "\n" +
+                        "    }\n" +
+                        "}\n");
+
+        // find the method call expression foo()
+        MethodCallExpr actual = cu.findFirst(MethodCallExpr.class).orElse(null);
+
+        MethodCallExpr expected = cu.getType(0).getMember(0)
+                .asMethodDeclaration().getBody().get().getStatement(0)
+                .asTryStmt().getFinallyBlock().get().getStatement(0)
+                .asTryStmt().getCatchClauses().get(0).getBody().getStatement(0)
+                .asExpressionStmt().getExpression()
+                .asMethodCallExpr();
+
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    void testFindAncestralFinallyBlock() {
+        CompilationUnit cu = parse(
+                "class Foo {\n" +
+                        "    void foo() {\n" +
+                        "        try {\n" +
+                        "        } catch (Exception e) {\n" +
+                        "        } finally {\n" +
+                        "            try {\n" +
+                        "            } catch (Exception e) {\n" +
+                        "                foo();\n" +
+                        "            } finally {\n" +
+                        "            }\n" +
+                        "        }\n" +
+                        "\n" +
+                        "    }\n" +
+                        "}\n");
+
+        // find the method call expression foo()
+        MethodCallExpr methodCallExpr = cu.findFirst(MethodCallExpr.class).orElse(null);
+
+        // find the finally block that the method call expression foo() is in
+        BlockStmt actual = methodCallExpr.findAncestor(BlockStmt.class, bs -> {
+            if (bs.getParentNode().isPresent() && bs.getParentNode().get() instanceof TryStmt) {
+                TryStmt ancestralTryStmt = (TryStmt) bs.getParentNode().get();
+                return bs == ancestralTryStmt.getFinallyBlock().orElse(null);
+            }
+            return false;
+        }).orElse(null);
+
+        BlockStmt expected = cu.getType(0).getMember(0)
+                .asMethodDeclaration().getBody().get().getStatement(0)
+                .asTryStmt().getFinallyBlock().get();
+
+        assertEquals(expected, actual);
+    }
+}
+
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodeListTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodeListTest.java
new file mode 100644
index 0000000..ddd37b1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodeListTest.java
@@ -0,0 +1,326 @@
+/*
+ * 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;
+
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.ast.observer.AstObserver;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.type.PrimitiveType;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.ast.NodeList.nodeList;
+import static org.junit.jupiter.api.Assertions.*;
+
+class NodeListTest {
+
+    private AstObserver createObserver(List<String> changes) {
+        return new AstObserver() {
+            @Override
+            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add(String.format("change of property %s for %s: from '%s' to '%s'", property, observedNode, oldValue, newValue));
+            }
+
+            @Override
+            public void parentChange(Node observedNode, Node previousParent, Node newParent) {
+                changes.add(String.format("setting parent for %s: was %s, now is %s", observedNode, previousParent, newParent));
+            }
+
+            @Override
+            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
+                changes.add(String.format("'%s' %s in list at %d", nodeAddedOrRemoved, type, index));
+            }
+
+            @Override
+            public void listReplacement(NodeList observedNode, int index, Node oldNode, Node newNode) {
+                changes.add(String.format("'%s' %s in list at %d", oldNode, ListChangeType.REMOVAL, index));
+                changes.add(String.format("'%s' %s in list at %d", newNode, ListChangeType.ADDITION, index));
+            }
+        };
+    }
+
+    private FieldDeclaration createIntField(String name) {
+        return new FieldDeclaration(new NodeList<>(), PrimitiveType.intType(), name);
+    }
+
+    @Test
+    void addAllWithoutIndex() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { void foo(int p) { }}";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().addAll(Arrays.asList(createIntField("a"), createIntField("b"), createIntField("c")));
+        assertEquals(Arrays.asList("'int a;' ADDITION in list at 1",
+                "'int b;' ADDITION in list at 2",
+                "'int c;' ADDITION in list at 3"), changes);
+    }
+
+    @Test
+    void addAllWithIndex() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { void foo(int p) { }}";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().addAll(0, Arrays.asList(createIntField("a"), createIntField("b"), createIntField("c")));
+        assertEquals(Arrays.asList("'int a;' ADDITION in list at 0",
+                "'int b;' ADDITION in list at 1",
+                "'int c;' ADDITION in list at 2"), changes);
+    }
+
+    @Test
+    void clear() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().clear();
+        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0",
+                "'int b;' REMOVAL in list at 0",
+                "'int c;' REMOVAL in list at 0"), changes);
+    }
+
+    @Test
+    void set() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().set(1, createIntField("d"));
+        assertEquals(Arrays.asList("'int b;' REMOVAL in list at 1",
+                "'int d;' ADDITION in list at 1"), changes);
+    }
+
+    @Test
+    void removeNode() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; int d; int e; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().remove(cd.getFieldByName("c").get());
+        assertEquals(Arrays.asList("'int c;' REMOVAL in list at 2"), changes);
+    }
+
+    @Test
+    void removeFirstNode() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; int d; int e; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().removeFirst();
+        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0"), changes);
+        assertEquals(cd.getMembers().size(), 4);
+
+        for (int i = 3; i >= 0; i--) {
+            assertNotNull(cd.getMembers().removeFirst());
+            assertEquals(cd.getMembers().size(), i);
+        }
+
+        assertEquals(cd.getMembers().size(), 0);
+    }
+
+    @Test
+    void removeLastNode() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; int d; int e; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().removeLast();
+        assertEquals(Arrays.asList("'int e;' REMOVAL in list at 4"), changes);
+        assertEquals(cd.getMembers().size(), 4);
+
+        for (int i = 3; i >= 0; i--) {
+            assertNotNull(cd.getMembers().removeLast());
+            assertEquals(cd.getMembers().size(), i);
+        }
+
+        assertEquals(cd.getMembers().size(), 0);
+    }
+
+    @Test
+    void removeObject() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; int d; int e; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().remove("hi");
+        assertEquals(Arrays.asList(), changes);
+    }
+
+    @Test
+    void removeAll() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; int d; int e; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().removeAll(Arrays.asList(cd.getFieldByName("b").get(), "foo", cd.getFieldByName("d").get()));
+        assertEquals(Arrays.asList("'int b;' REMOVAL in list at 1",
+                "'int d;' REMOVAL in list at 2"), changes);
+    }
+
+    @Test
+    void retainAll() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; int d; int e; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().retainAll(Arrays.asList(cd.getFieldByName("b").get(), "foo", cd.getFieldByName("d").get()));
+        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0",
+                "'int c;' REMOVAL in list at 1",
+                "'int e;' REMOVAL in list at 2"), changes);
+    }
+
+    @Test
+    void replaceAll() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int b; int c; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().replaceAll(bodyDeclaration -> {
+            FieldDeclaration clone = (FieldDeclaration) bodyDeclaration.clone();
+            SimpleName id = clone.getVariable(0).getName();
+            id.setIdentifier(id.getIdentifier().toUpperCase());
+            return clone;
+        });
+        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0", "'int A;' ADDITION in list at 0",
+                "'int b;' REMOVAL in list at 1", "'int B;' ADDITION in list at 1",
+                "'int c;' REMOVAL in list at 2", "'int C;' ADDITION in list at 2"), changes);
+    }
+
+    @Test
+    void removeIf() {
+        List<String> changes = new LinkedList<>();
+        String code = "class A { int a; int longName; int c; }";
+        CompilationUnit cu = parse(code);
+        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
+        cd.getMembers().register(createObserver(changes));
+
+        cd.getMembers().removeIf(m -> ((FieldDeclaration) m).getVariable(0).getName().getIdentifier().length() > 3);
+        assertEquals(Arrays.asList("'int longName;' REMOVAL in list at 1"), changes);
+    }
+
+    @Test
+    void replace() {
+        final NodeList<Name> list = nodeList(new Name("a"), new Name("b"), new Name("c"));
+
+        final boolean replaced = list.replace(new Name("b"), new Name("z"));
+
+        assertTrue(replaced);
+        assertEquals(3, list.size());
+        assertEquals("a", list.get(0).asString());
+        assertEquals("z", list.get(1).asString());
+        assertEquals("c", list.get(2).asString());
+    }
+
+    @Test
+    void toStringTest() {
+        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), new Name("cde"));
+
+        assertEquals("[abc, bcd, cde]", list.toString());
+    }
+
+    @Test
+    void addFirst() {
+        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), new Name("cde"));
+
+        list.addFirst(new Name("xxx"));
+
+        assertEquals("[xxx, abc, bcd, cde]", list.toString());
+    }
+
+    @Test
+    void addLast() {
+        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), new Name("cde"));
+
+        list.addLast(new Name("xxx"));
+
+        assertEquals("[abc, bcd, cde, xxx]", list.toString());
+    }
+
+    @Test
+    void addBefore() {
+        Name n = new Name("bcd");
+        final NodeList<Name> list = nodeList(new Name("abc"), n, new Name("cde"));
+
+        list.addBefore(new Name("xxx"), n);
+
+        assertEquals("[abc, xxx, bcd, cde]", list.toString());
+    }
+
+    @Test
+    void addAfter() {
+        Name n = new Name("bcd");
+        final NodeList<Name> list = nodeList(new Name("abc"), n, new Name("cde"));
+
+        list.addAfter(new Name("xxx"), n);
+
+        assertEquals("[abc, bcd, xxx, cde]", list.toString());
+    }
+
+    @Test
+    void addBeforeFirst() {
+        Name abc = new Name("abc");
+        final NodeList<Name> list = nodeList(abc, new Name("bcd"), new Name("cde"));
+
+        list.addBefore(new Name("xxx"), abc);
+
+        assertEquals("[xxx, abc, bcd, cde]", list.toString());
+    }
+
+    @Test
+    void addAfterLast() {
+        Name cde = new Name("cde");
+        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), cde);
+
+        list.addAfter(new Name("xxx"), cde);
+
+        assertEquals("[abc, bcd, cde, xxx]", list.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodePositionTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodePositionTest.java
new file mode 100644
index 0000000..198245c
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodePositionTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+import com.github.javaparser.*;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NodePositionTest {
+
+    private List<Node> getAllNodes(Node node) {
+        List<Node> nodes = new LinkedList<>();
+        nodes.add(node);
+        node.getChildNodes().forEach(c -> nodes.addAll(getAllNodes(c)));
+        return nodes;
+    }
+
+    @Test
+    void packageProtectedClassShouldHavePositionSet() throws IOException {
+        ensureAllNodesHaveValidBeginPosition("class A { }");
+    }
+
+    @Test
+    void packageProtectedInterfaceShouldHavePositionSet() throws IOException {
+        ensureAllNodesHaveValidBeginPosition("interface A { }");
+    }
+
+    @Test
+    void packageProtectedEnumShouldHavePositionSet() throws IOException {
+        ensureAllNodesHaveValidBeginPosition("enum A { }");
+    }
+
+    @Test
+    void packageProtectedAnnotationShouldHavePositionSet() throws IOException {
+        ensureAllNodesHaveValidBeginPosition("@interface A { }");
+    }
+
+    @Test
+    void packageProtectedFieldShouldHavePositionSet() throws IOException {
+        ensureAllNodesHaveValidBeginPosition("public class A { int i; }");
+    }
+
+    @Test
+    void packageProtectedMethodShouldHavePositionSet() throws IOException {
+      ensureAllNodesHaveValidBeginPosition("public class A { void foo() {} }");
+    }
+
+    @Test
+    void packageProtectedConstructorShouldHavePositionSet() throws IOException {
+      ensureAllNodesHaveValidBeginPosition("public class A { A() {} }");
+    }
+
+    private void ensureAllNodesHaveValidBeginPosition(final String code) {
+        ParseResult<CompilationUnit> res = new JavaParser().parse(ParseStart.COMPILATION_UNIT, Providers.provider(code));
+        assertTrue(res.getProblems().isEmpty());
+
+        CompilationUnit cu = res.getResult().get();
+        getAllNodes(cu).forEach(n -> {
+            assertNotNull(n.getRange(), String.format("There should be no node without a range: %s (class: %s)",
+                    n, n.getClass().getCanonicalName()));
+            if (n.getBegin().get().line == 0 && !n.toString().isEmpty()) {
+                throw new IllegalArgumentException("There should be no node at line 0: " + n + " (class: "
+                        + n.getClass().getCanonicalName() + ")");
+            }
+        });
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodeTest.java
new file mode 100644
index 0000000..2319c4a
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/NodeTest.java
@@ -0,0 +1,446 @@
+/*
+ * 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;
+
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+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.Expression;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.ast.observer.AstObserver;
+import com.github.javaparser.ast.observer.AstObserverAdapter;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.type.PrimitiveType;
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.*;
+
+class NodeTest {
+
+    @Test
+    void registerSubTree() {
+        String code = "class A { int f; void foo(int p) { return 'z'; }}";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new AstObserverAdapter() {
+            @Override
+            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
+            }
+        };
+        cu.registerForSubtree(observer);
+
+        assertEquals(Arrays.asList(), changes);
+
+        cu.getClassByName("A").get().setName("MyCoolClass");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean",
+                "Parameter.name changed from p to myParam"), changes);
+    }
+
+    @Test
+    void registerWithJustNodeMode() {
+        String code = "class A { int f; void foo(int p) { return 'z'; }}";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new AstObserverAdapter() {
+            @Override
+            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
+            }
+        };
+        cu.getClassByName("A").get().register(observer, Node.ObserverRegistrationMode.JUST_THIS_NODE);
+
+        assertEquals(Arrays.asList(), changes);
+
+        cu.getClassByName("A").get().setName("MyCoolClass");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
+
+        cu.getClassByName("MyCoolClass").get().addField("int", "bar").getVariables().get(0).setInitializer("0");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
+    }
+
+    @Test
+    void registerWithNodeAndExistingDescendantsMode() {
+        String code = "class A { int f; void foo(int p) { return 'z'; }}";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new AstObserverAdapter() {
+            @Override
+            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
+            }
+        };
+        cu.getClassByName("A").get().register(observer, Node.ObserverRegistrationMode.THIS_NODE_AND_EXISTING_DESCENDANTS);
+
+        assertEquals(Arrays.asList(), changes);
+
+        cu.getClassByName("A").get().setName("MyCoolClass");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean",
+                "Parameter.name changed from p to myParam"), changes);
+
+        cu.getClassByName("MyCoolClass").get().addField("int", "bar").getVariables().get(0).setInitializer("0");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean",
+                "Parameter.name changed from p to myParam"), changes);
+    }
+
+    @Test
+    void registerWithSelfPropagatingMode() {
+        String code = "class A { int f; void foo(int p) { return 'z'; }}";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new AstObserverAdapter() {
+            @Override
+            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
+            }
+        };
+        cu.getClassByName("A").get().register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
+
+        assertEquals(Arrays.asList(), changes);
+
+        cu.getClassByName("A").get().setName("MyCoolClass");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean"), changes);
+
+        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean",
+                "Parameter.name changed from p to myParam"), changes);
+
+        cu.getClassByName("MyCoolClass").get()
+                .addField("int", "bar")
+                .getVariables().get(0).setInitializer("0");
+        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
+                "FieldDeclaration.maximum_common_type changed from int to boolean",
+                "VariableDeclarator.type changed from int to boolean",
+                "Parameter.name changed from p to myParam",
+                "VariableDeclarator.initializer changed from null to 0"), changes);
+    }
+
+    @Test
+    void deleteAParameterTriggerNotifications() {
+        String code = "class A { void foo(int p) { }}";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new AstObserverAdapter() {
+
+            @Override
+            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
+                changes.add("removing [" + nodeAddedOrRemoved + "] from index " + index);
+            }
+        };
+        cu.register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
+
+        cu.getClassByName("A").get().getMethodsByName("foo").get(0).getParameter(0).remove();
+        assertEquals(Arrays.asList("removing [int p] from index 0"), changes);
+    }
+
+    @Test
+    void deleteClassNameDoesNotTriggerNotifications() {
+        String code = "class A { void foo(int p) { }}";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new AstObserverAdapter() {
+
+            @Override
+            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
+                changes.add("removing [" + nodeAddedOrRemoved + "] from index " + index);
+            }
+        };
+        cu.register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
+
+        // I cannot remove the name of a type
+        assertFalse(cu.getClassByName("A").get().getName().remove());
+        assertEquals(Arrays.asList(), changes);
+    }
+
+    @Test
+    void deleteMethodBodyDoesTriggerNotifications() {
+        String code = "class A { void foo(int p) { }}";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new AstObserverAdapter() {
+
+            @Override
+            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add("setting [" + property + "] to " + newValue);
+            }
+
+            @Override
+            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
+                changes.add("removing [" + nodeAddedOrRemoved + "] from index " + index);
+            }
+        };
+        cu.register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
+
+        assertTrue(cu.getClassByName("A").get().getMethodsByName("foo").get(0).getBody().get().remove());
+        assertEquals(Arrays.asList("setting [BODY] to null"), changes);
+    }
+
+    @Test
+    void removeOrphanCommentPositiveCase() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(), false, "A");
+        Comment c = new LineComment("A comment");
+        decl.addOrphanComment(c);
+        assertEquals(1, decl.getOrphanComments().size());
+        assertSame(decl, c.getParentNode().get());
+        assertTrue(decl.removeOrphanComment(c));
+        assertEquals(0, decl.getOrphanComments().size());
+        assertFalse(c.getParentNode().isPresent());
+    }
+
+    @Test
+    void removeOrphanCommentNegativeCase() {
+        ClassOrInterfaceDeclaration aClass = new ClassOrInterfaceDeclaration(new NodeList<>(), false, "A");
+        FieldDeclaration aField = new FieldDeclaration(new NodeList<>(), new VariableDeclarator(PrimitiveType.intType(), "f"));
+        aClass.getMembers().add(aField);
+        Comment c = new LineComment("A comment");
+        aField.addOrphanComment(c);
+        // the comment is an orphan comment of the field, so trying to remove it on the class should not work
+        assertFalse(aClass.removeOrphanComment(c));
+        assertEquals(1, aField.getOrphanComments().size());
+        assertTrue(c.getParentNode().isPresent());
+    }
+
+    @Test
+    void hasJavaDocCommentPositiveCaseWithSetJavaDocComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.setJavadocComment("A comment");
+        assertTrue(decl.hasJavaDocComment());
+    }
+
+    @Test
+    void hasJavaDocCommentPositiveCaseWithSetComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.setComment(new JavadocComment("A comment"));
+        assertTrue(decl.hasJavaDocComment());
+    }
+
+    @Test
+    void hasJavaDocCommentNegativeCaseNoComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        assertFalse(decl.hasJavaDocComment());
+    }
+
+    @Test
+    void hasJavaDocCommentNegativeCaseLineComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.setComment(new LineComment("foo"));
+        assertFalse(decl.hasJavaDocComment());
+    }
+
+    @Test
+    void hasJavaDocCommentNegativeCaseBlockComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.setComment(new BlockComment("foo"));
+        assertFalse(decl.hasJavaDocComment());
+    }
+
+    @Test
+    void findCompilationUnitOfCommentNode() {
+        CompilationUnit cu = parse("class X {\n" +
+                "  void x() {\n" +
+                "    // this is a comment\n" +
+                "    foo();\n" +
+                "  }\n" +
+                "}\n");
+
+        Comment comment = cu.getType(0).getMember(0)
+                .asMethodDeclaration().getBody().get()
+                .getStatement(0).getComment().get();
+
+        assertTrue(comment.findCompilationUnit().isPresent());
+    }
+
+    @Test
+    void findCompilationUnitOfOrphanCommentNode() {
+        CompilationUnit cu = parse("class X {\n" +
+                "  void x() {\n" +
+                "    // this is a comment\n" +
+                "  }\n" +
+                "}\n");
+
+        Comment comment = cu.getType(0).getMember(0)
+                .asMethodDeclaration().getBody().get()
+                .getOrphanComments().get(0);
+
+        assertTrue(comment.findCompilationUnit().isPresent());
+    }
+
+    @Test
+    void removeAllOnRequiredProperty() {
+        CompilationUnit cu = parse("class X{ void x(){}}");
+        MethodDeclaration methodDeclaration = cu.getType(0).getMethods().get(0);
+        methodDeclaration.getName().removeForced();
+        // Name is required, so to remove it the whole method is removed.
+        assertEquals(String.format("class X {%1$s}%1$s", EOL), cu.toString());
+    }
+
+    @Test
+    void removingTheSecondOfAListOfIdenticalStatementsDoesNotMessUpTheParents() {
+        CompilationUnit unit = parse(String.format("public class Example {%1$s" +
+                "  public static void example() {%1$s" +
+                "    boolean swapped;%1$s" +
+                "    swapped=false;%1$s" +
+                "    swapped=false;%1$s" +
+                "  }%1$s" +
+                "}%1$s", EOL));
+        // remove the second swapped=false
+        ExpressionStmt target = unit.findAll(ExpressionStmt.class).get(2);
+        target.remove();
+        // This will throw an exception if the parents are bad.
+        unit.toString();
+    }
+
+    @Test
+    void findCompilationUnit() {
+        CompilationUnit cu = parse("class X{int x;}");
+        VariableDeclarator x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariables().get(0);
+        assertEquals(cu, x.findCompilationUnit().get());
+    }
+
+    @Test
+    void findParent() {
+        CompilationUnit cu = parse("class X{int x;}");
+        SimpleName x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariables().get(0).getName();
+        assertEquals("int x;", x.findAncestor(FieldDeclaration.class).get().toString());
+    }
+
+    @Test
+    void cantFindCompilationUnit() {
+        VariableDeclarator x = new VariableDeclarator();
+        assertFalse(x.findCompilationUnit().isPresent());
+    }
+
+    @Test
+    void genericWalk() {
+        Expression e = parseExpression("1+1");
+        StringBuilder b = new StringBuilder();
+        e.walk(n -> b.append(n.toString()));
+        assertEquals("1 + 111", b.toString());
+    }
+
+    @Test
+    void classSpecificWalk() {
+        Expression e = parseExpression("1+1");
+        StringBuilder b = new StringBuilder();
+        e.walk(IntegerLiteralExpr.class, n -> b.append(n.toString()));
+        assertEquals("11", b.toString());
+    }
+
+    @Test
+    void conditionalFindAll() {
+        Expression e = parseExpression("1+2+3");
+        List<IntegerLiteralExpr> ints = e.findAll(IntegerLiteralExpr.class, n -> n.asInt() > 1);
+        assertEquals("[2, 3]", ints.toString());
+    }
+
+    @Test
+    void typeOnlyFindAll() {
+        Expression e = parseExpression("1+2+3");
+        List<IntegerLiteralExpr> ints = e.findAll(IntegerLiteralExpr.class);
+        assertEquals("[1, 2, 3]", ints.toString());
+    }
+
+    @Test
+    void typeOnlyFindAllMatchesSubclasses() {
+        Expression e = parseExpression("1+2+3");
+        List<Node> ints = e.findAll(Node.class);
+        assertEquals("[1 + 2 + 3, 1 + 2, 1, 2, 3]", ints.toString());
+    }
+
+    @Test
+    void conditionalTypedFindFirst() {
+        Expression e = parseExpression("1+2+3");
+        Optional<IntegerLiteralExpr> ints = e.findFirst(IntegerLiteralExpr.class, n -> n.asInt() > 1);
+        assertEquals("Optional[2]", ints.toString());
+    }
+
+    @Test
+    void typeOnlyFindFirst() {
+        Expression e = parseExpression("1+2+3");
+        Optional<IntegerLiteralExpr> ints = e.findFirst(IntegerLiteralExpr.class);
+        assertEquals("Optional[1]", ints.toString());
+    }
+
+    @Test
+    void stream() {
+        Expression e = parseExpression("1+2+3");
+        List<IntegerLiteralExpr> ints = e.stream()
+                .filter(n -> n instanceof IntegerLiteralExpr)
+                .map(IntegerLiteralExpr.class::cast)
+                .filter(i -> i.asInt() > 1)
+                .collect(Collectors.toList());
+        assertEquals("[2, 3]", ints.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java
new file mode 100644
index 0000000..2737a06
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.Problem;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.ast.Node.Parsedness.PARSED;
+import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ParseResultTest {
+    private final JavaParser javaParser = new JavaParser(new ParserConfiguration());
+
+    @Test
+    void whenParsingSucceedsThenWeGetResultsAndNoProblems() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{}"));
+
+        assertThat(result.getResult().isPresent()).isTrue();
+        assertThat(result.getResult().get().getParsed()).isEqualTo(PARSED);
+        assertThat(result.getProblems()).isEmpty();
+
+        assertThat(result.toString()).isEqualTo("Parsing successful");
+    }
+
+    @Test
+    void whenParsingFailsThenWeGetProblemsAndABadResult() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class {"));
+
+        assertThat(result.getResult().isPresent()).isTrue();
+        assertThat(result.getResult().get().getParsed()).isEqualTo(UNPARSABLE);
+        assertThat(result.getProblems().size()).isEqualTo(1);
+
+        Problem problem = result.getProblem(0);
+        assertThat(problem.getMessage()).isEqualTo("Parse error. Found \"{\", expected one of  \"enum\" \"exports\" \"module\" \"open\" \"opens\" \"provides\" \"requires\" \"strictfp\" \"to\" \"transitive\" \"uses\" \"with\" <IDENTIFIER>");
+
+        assertThat(result.toString()).startsWith("Parsing failed:" + EOL + "(line 1,col 1) Parse error.");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ReplaceNodeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ReplaceNodeTest.java
new file mode 100644
index 0000000..7b3bbb6
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/ReplaceNodeTest.java
@@ -0,0 +1,32 @@
+package com.github.javaparser.ast;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parsePackageDeclaration;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ReplaceNodeTest {
+    @Test
+    void testSimplePropertyWithGenericReplace() {
+        CompilationUnit cu = parse("package x; class Y {}");
+        cu.replace(cu.getPackageDeclaration().get(), parsePackageDeclaration("package z;"));
+        assertEquals(String.format("package z;%1$s" +
+                "%1$s" +
+                "class Y {%1$s" +
+                "}%1$s", EOL), cu.toString());
+    }
+
+    @Test
+    void testListProperty() {
+        CompilationUnit cu = parse("package x; class Y {}");
+        cu.replace(cu.getClassByName("Y").get(), parse("class B{int y;}").getClassByName("B").get());
+        assertEquals(String.format("package x;%1$s" +
+                "%1$s" +
+                "class B {%1$s" +
+                "%1$s" +
+                "    int y;%1$s" +
+                "}%1$s", EOL), cu.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/AnnotationDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/AnnotationDeclarationTest.java
new file mode 100644
index 0000000..89d50a7
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/AnnotationDeclarationTest.java
@@ -0,0 +1,21 @@
+package com.github.javaparser.ast.body;
+
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.TestParser.parseStatement;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class AnnotationDeclarationTest {
+    @Test
+    void cantAddField() {
+        assertThrows(IllegalStateException.class, () -> new AnnotationDeclaration().addField(Object.class, "oo"));
+    }
+
+    @Test
+    void issue2216() {
+        Statement statement = parseStatement("TT tt = new <String> @TypeAnno @TA2 TT( \"S\" );");
+        assertEquals("TT tt = new <String> @TypeAnno @TA2 TT(\"S\");", statement.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/AnnotationMemberDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/AnnotationMemberDeclarationTest.java
new file mode 100644
index 0000000..ca54686
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/AnnotationMemberDeclarationTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.body;
+
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.SimpleName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class AnnotationMemberDeclarationTest {
+
+    @Test
+    void whenSettingNameTheParentOfNameIsAssigned() {
+        AnnotationMemberDeclaration decl = new AnnotationMemberDeclaration();
+        SimpleName name = new SimpleName("foo");
+        decl.setName(name);
+        assertTrue(name.getParentNode().isPresent());
+        assertSame(decl, name.getParentNode().get());
+    }
+
+    @Test
+    void removeDefaultValueWhenNoDefaultValueIsPresent() {
+        AnnotationMemberDeclaration decl = new AnnotationMemberDeclaration();
+        SimpleName name = new SimpleName("foo");
+        decl.setName(name);
+
+        decl.removeDefaultValue();
+
+        assertFalse(decl.getDefaultValue().isPresent());
+    }
+
+    @Test
+    void removeDefaultValueWhenDefaultValueIsPresent() {
+        AnnotationMemberDeclaration decl = new AnnotationMemberDeclaration();
+        SimpleName name = new SimpleName("foo");
+        decl.setName(name);
+        Expression defaultValue = new IntegerLiteralExpr("2");
+        decl.setDefaultValue(defaultValue);
+
+        decl.removeDefaultValue();
+
+        assertFalse(defaultValue.getParentNode().isPresent());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java
new file mode 100644
index 0000000..60d0edd
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java
@@ -0,0 +1,61 @@
+package com.github.javaparser.ast.body;
+
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class ClassOrInterfaceDeclarationTest {
+    @Test
+    void staticNestedClass() {
+        CompilationUnit cu = parse("class X{static class Y{}}");
+        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get().getMembers().get(0).asClassOrInterfaceDeclaration();
+
+        assertFalse(y.isInnerClass());
+        assertTrue(y.isNestedType());
+        assertFalse(y.isLocalClassDeclaration());
+    }
+
+    @Test
+    void nestedInterface() {
+        CompilationUnit cu = parse("class X{interface Y{}}");
+        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get().getMembers().get(0).asClassOrInterfaceDeclaration();
+
+        assertFalse(y.isInnerClass());
+        assertTrue(y.isNestedType());
+        assertFalse(y.isLocalClassDeclaration());
+    }
+
+    @Test
+    void nonStaticNestedClass() {
+        CompilationUnit cu = parse("class X{class Y{}}");
+        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get().getMembers().get(0).asClassOrInterfaceDeclaration();
+
+        assertTrue(y.isInnerClass());
+        assertTrue(y.isNestedType());
+        assertFalse(y.isLocalClassDeclaration());
+    }
+
+    @Test
+    void topClass() {
+        CompilationUnit cu = parse("class X{}");
+        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get();
+
+        assertFalse(y.isInnerClass());
+        assertFalse(y.isNestedType());
+        assertFalse(y.isLocalClassDeclaration());
+    }
+
+    @Test
+    void localClass() {
+        MethodDeclaration method = parseBodyDeclaration("void x(){class X{};}").asMethodDeclaration();
+        ClassOrInterfaceDeclaration x = method.findFirst(ClassOrInterfaceDeclaration.class).get();
+
+        assertFalse(x.isInnerClass());
+        assertFalse(x.isNestedType());
+        assertTrue(x.isLocalClassDeclaration());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ConstructorDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ConstructorDeclarationTest.java
new file mode 100644
index 0000000..86b6489
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/ConstructorDeclarationTest.java
@@ -0,0 +1,18 @@
+package com.github.javaparser.ast.body;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ConstructorDeclarationTest {
+    @Test
+    void acceptsSuper() {
+        ConstructorDeclaration cons = new ConstructorDeclaration("Cons");
+        cons.createBody().addStatement("super();");
+
+        assertEquals(String.format("public Cons() {%1$s" +
+                "    super();%1$s" +
+                "}", EOL), cons.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java
new file mode 100644
index 0000000..206a650
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java
@@ -0,0 +1,24 @@
+package com.github.javaparser.ast.body;
+
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class FieldDeclarationTest {
+    @Test
+    void wofjweoifj() {
+        CompilationUnit compilationUnit = parse("" +
+                "class A {\n" +
+                "    int a, b;\n" +
+                "}");
+
+        BodyDeclaration<?> declaration = compilationUnit.getType(0).getMembers().get(0);
+        FieldDeclaration fieldDeclaration = declaration.asFieldDeclaration();
+        VariableDeclarator var1 = fieldDeclaration.getVariables().get(0);
+        VariableDeclarator var2 = fieldDeclaration.getVariables().get(1);
+        assertEquals(var1, var1.getType().getParentNode().get());
+        assertEquals(var2, var2.getType().getParentNode().get());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/MethodDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/MethodDeclarationTest.java
new file mode 100644
index 0000000..389936f
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/MethodDeclarationTest.java
@@ -0,0 +1,86 @@
+package com.github.javaparser.ast.body;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+class MethodDeclarationTest {
+    @Test
+    void annotationsAllowedAfterGenericsAndBeforeReturnType() {
+        parseBodyDeclaration("public <T> @Abc String method() {return null;}");
+    }
+
+    @Test
+    void annotationsAllowedBeforeGenerics() {
+        parseBodyDeclaration("public @Abc <T> String method() {return null;}");
+    }
+
+    @Test
+    void explicitReceiverParameters1() {
+        MethodDeclaration method = parseBodyDeclaration("void InnerInner(@mypackage.Anno Source.@mypackage.Anno Inner Source.Inner.this) { }").asMethodDeclaration();
+        assertEquals("Source.Inner.this", method.getReceiverParameter().get().getNameAsString());
+    }
+
+    @Test
+    void explicitReceiverParameters2() {
+        MethodDeclaration method = parseBodyDeclaration("void x(A this) { }").asMethodDeclaration();
+        assertEquals("this", method.getReceiverParameter().get().getNameAsString());
+    }
+
+    @Test
+    void explicitReceiverParameters3() {
+        MethodDeclaration method = parseBodyDeclaration("void x(A that) { }").asMethodDeclaration();
+        assertFalse(method.getReceiverParameter().isPresent());
+    }
+
+    @Test
+    void signaturesEqual() {
+        MethodDeclaration method1 = parseBodyDeclaration("void x(String a) { }").asMethodDeclaration();
+        MethodDeclaration method2 = parseBodyDeclaration("int x(String z);").asMethodDeclaration();
+        assertEquals(method1.getSignature(), method2.getSignature());
+    }
+
+    @Test
+    void signaturesEqualWhenGenericsDiffer() {
+        MethodDeclaration method1 = parseBodyDeclaration("void x(List<Long> a) { }").asMethodDeclaration();
+        MethodDeclaration method2 = parseBodyDeclaration("void x(List<Integer> a) { }").asMethodDeclaration();
+        assertEquals(method1.getSignature(), method2.getSignature());
+    }
+
+    @Test
+    void signaturesEqualWhenAnnotationsDiffer() {
+        MethodDeclaration method1 = parseBodyDeclaration("void x(@A @B List a) { }").asMethodDeclaration();
+        MethodDeclaration method2 = parseBodyDeclaration("void x(@C List a) { }").asMethodDeclaration();
+        assertEquals(method1.getSignature(), method2.getSignature());
+    }
+
+    @Test
+    void signaturesDifferentName() {
+        MethodDeclaration method1 = parseBodyDeclaration("void x(String a) { }").asMethodDeclaration();
+        MethodDeclaration method2 = parseBodyDeclaration("int y(String z);").asMethodDeclaration();
+        assertNotEquals(method1.getSignature(), method2.getSignature());
+    }
+
+    @Test
+    void signaturesDifferentTypes() {
+        MethodDeclaration method1 = parseBodyDeclaration("void x(String a) { }").asMethodDeclaration();
+        MethodDeclaration method2 = parseBodyDeclaration("int x(int z);").asMethodDeclaration();
+        assertNotEquals(method1.getSignature(), method2.getSignature());
+    }
+
+    @Test
+    void signaturesDifferentVarargs() {
+        MethodDeclaration method1 = parseBodyDeclaration("int x(int z);").asMethodDeclaration();
+        MethodDeclaration method2 = parseBodyDeclaration("int x(int... z);").asMethodDeclaration();
+        assertNotEquals(method1.getSignature(), method2.getSignature());
+    }
+
+    @Test
+    void signatureToString() {
+        MethodDeclaration method1 = parseBodyDeclaration("int x(int z, String q);").asMethodDeclaration();
+        assertEquals("x(int, String)", method1.getSignature().toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/TypeDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/TypeDeclarationTest.java
new file mode 100644
index 0000000..1db3c8f
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/body/TypeDeclarationTest.java
@@ -0,0 +1,64 @@
+package com.github.javaparser.ast.body;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.TestParser.parseBodyDeclaration;
+import static com.github.javaparser.utils.TestParser.parseCompilationUnit;
+import static java.util.stream.Collectors.joining;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class TypeDeclarationTest {
+    @Test
+    void qualifiedNameOfClassInDefaultPackage() {
+        assertFQN("X", parseCompilationUnit("class X{ }"));
+    }
+
+    @Test
+    void qualifiedNameOfClassInAPackage() {
+        assertFQN("a.b.c.X", parseCompilationUnit("package a.b.c; class X{}"));
+    }
+
+    @Test
+    void qualifiedNameOfInterfaceInAPackage() {
+        assertFQN("a.b.c.X", parseCompilationUnit("package a.b.c; interface X{}"));
+    }
+
+    @Test
+    void qualifiedNameOfEnumInAPackage() {
+        assertFQN("a.b.c.X", parseCompilationUnit("package a.b.c; enum X{}"));
+    }
+
+    @Test
+    void qualifiedNameOfAnnotationInAPackage() {
+        assertFQN("a.b.c.X", parseCompilationUnit("package a.b.c; @interface X{}"));
+    }
+
+    @Test
+    void qualifiedNameOfNestedClassInAPackage() {
+        assertFQN("a.b.c.Outer,a.b.c.Outer.Nested", parseCompilationUnit("package a.b.c; class Outer{ class Nested {} }"));
+    }
+
+    @Test
+    void qualifiedNameOfAnonymousClassCantBeQueried() {
+        assertFQN("X", parseCompilationUnit("class X{ int aaa() {new Object(){};} }"));
+    }
+
+    @Test
+    void qualifiedNameOfLocalClassIsEmpty() {
+        assertFQN("X,?", parseCompilationUnit("class X{ int aaa() {class Local {}} }"));
+    }
+
+    @Test
+    void qualifiedNameOfDetachedClassIsEmpty() {
+        assertFQN("?", parseBodyDeclaration("class X{}"));
+    }
+
+    void assertFQN(String fqn, Node node) {
+        assertEquals(fqn, node.findAll(TypeDeclaration.class).stream()
+                .map(td -> (TypeDeclaration<?>) td)
+                .map(td -> td.getFullyQualifiedName().orElse("?"))
+                .collect(joining(",")));
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/comments/CommentTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/comments/CommentTest.java
new file mode 100644
index 0000000..1fb4443
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/comments/CommentTest.java
@@ -0,0 +1,191 @@
+/*
+ * 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.comments;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.javadoc.Javadoc;
+import com.github.javaparser.javadoc.description.JavadocDescription;
+import com.github.javaparser.printer.PrettyPrinterConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.*;
+
+class CommentTest {
+
+    private static final PrettyPrinterConfiguration PRETTY_PRINTER_CONFIG_TWO_INDENT = new PrettyPrinterConfiguration().setIndentSize(2);
+
+    @Test
+    void removeOrphanComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(), false, "A");
+        Comment c = new LineComment("A comment");
+        decl.addOrphanComment(c);
+        assertEquals(1, decl.getOrphanComments().size());
+        assertTrue(c.remove());
+        assertEquals(0, decl.getOrphanComments().size());
+    }
+
+    @Test
+    void removeAssociatedComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(), false, "A");
+        Comment c = new LineComment("A comment");
+        decl.setComment(c);
+        assertTrue(decl.getComment().isPresent());
+        assertTrue(c.remove());
+        assertFalse(decl.getComment().isPresent());
+    }
+
+    @Test
+    void cannotRemoveCommentNotUsedAnywhere() {
+        Comment c = new LineComment("A comment");
+        assertFalse(c.remove());
+    }
+
+    @Test
+    void unicodeEscapesArePreservedInComments() {
+        CompilationUnit cu = parse("// xxx\\u2122xxx");
+        Comment comment = cu.getAllContainedComments().get(0);
+        assertEquals(" xxx\\u2122xxx", comment.getContent());
+    }
+
+    @Test
+    void testReplaceDuplicateJavaDocComment() {
+        // Arrange
+        CompilationUnit cu = parse("public class MyClass {" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void oneMethod() {" + EOL +
+                "  }" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void anotherMethod() {" + EOL +
+                "  }" + EOL +
+                "}" + EOL);
+
+        MethodDeclaration methodDeclaration = cu.findFirst(MethodDeclaration.class).get();
+
+        // Act
+        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("Change Javadoc"));
+        methodDeclaration.setJavadocComment("", javadoc);
+
+        // Assert
+        assertEqualsNoEol("public class MyClass {\n" +
+                "\n" +
+                "  /**\n" +
+                "   * Change Javadoc\n" +
+                "   */\n" +
+                "  public void oneMethod() {\n" +
+                "  }\n" +
+                "\n" +
+                "  /**\n" +
+                "   * Comment A\n" +
+                "   */\n" +
+                "  public void anotherMethod() {\n" +
+                "  }\n" +
+                "}\n", cu.toString(PRETTY_PRINTER_CONFIG_TWO_INDENT));
+    }
+
+    @Test
+    void testRemoveDuplicateComment() {
+        // Arrange
+        CompilationUnit cu = parse("public class MyClass {" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void oneMethod() {" + EOL +
+                "  }" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void anotherMethod() {" + EOL +
+                "  }" + EOL +
+                "}" +
+                EOL);
+
+        MethodDeclaration methodDeclaration = cu.findFirst(MethodDeclaration.class).get();
+
+        // Act
+        methodDeclaration.removeComment();
+
+        // Assert
+        assertEqualsNoEol("public class MyClass {\n" +
+                "\n" +
+                "  public void oneMethod() {\n" +
+                "  }\n" +
+                "\n" +
+                "  /**\n" +
+                "   * Comment A\n" +
+                "   */\n" +
+                "  public void anotherMethod() {\n" +
+                "  }\n" +
+                "}\n", cu.toString(PRETTY_PRINTER_CONFIG_TWO_INDENT));
+    }
+
+    @Test
+    void testRemoveDuplicateJavaDocComment() {
+        // Arrange
+        CompilationUnit cu = parse("public class MyClass {" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void oneMethod() {" + EOL +
+                "  }" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void anotherMethod() {" + EOL +
+                "  }" + EOL +
+                "}" +
+                EOL);
+
+        MethodDeclaration methodDeclaration = cu.findAll(MethodDeclaration.class).get(1);
+
+        // Act
+        methodDeclaration.removeJavaDocComment();
+
+        // Assert
+        assertEqualsNoEol("public class MyClass {\n" +
+                "\n" +
+                "  /**\n" +
+                "   * Comment A\n" +
+                "   */\n" +
+                "  public void oneMethod() {\n" +
+                "  }\n" +
+                "\n" +
+                "  public void anotherMethod() {\n" +
+                "  }\n" +
+                "}\n", cu.toString(PRETTY_PRINTER_CONFIG_TWO_INDENT));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/AssignExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/AssignExprTest.java
new file mode 100644
index 0000000..4345d59
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/AssignExprTest.java
@@ -0,0 +1,12 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class AssignExprTest {
+    @Test
+    void convertOperator() {
+        assertEquals(BinaryExpr.Operator.PLUS, AssignExpr.Operator.PLUS.toBinaryOperator().get());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/BinaryExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/BinaryExprTest.java
new file mode 100644
index 0000000..2f3c4cf
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/BinaryExprTest.java
@@ -0,0 +1,12 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class BinaryExprTest {
+    @Test
+    void convertOperator() {
+        assertEquals(AssignExpr.Operator.PLUS, BinaryExpr.Operator.PLUS.toAssignOperator().get());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/CharLiteralExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/CharLiteralExprTest.java
new file mode 100644
index 0000000..df39d3f
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/CharLiteralExprTest.java
@@ -0,0 +1,51 @@
+package com.github.javaparser.ast.expr;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CharLiteralExprTest {
+    @Test
+    void parseSimpleChar() {
+        CharLiteralExpr c = parseExpression("'a'");
+        assertEquals("a", c.getValue());
+    }
+
+    @Test
+    void parseSimpleEscape() {
+        CharLiteralExpr c = parseExpression("'\\t'");
+        assertEquals("\\t", c.getValue());
+    }
+
+    @Test
+    void parseUnicode() {
+        CharLiteralExpr c = parseExpression("'Ω'");
+        assertEquals("Ω", c.getValue());
+    }
+
+    @Test
+    void parseNumericEscape() {
+        CharLiteralExpr c = parseExpression("'\\177'");
+        assertEquals("\\177", c.getValue());
+    }
+
+    @Test
+    void parseUnicodeEscape() {
+        CharLiteralExpr c = parseExpression("'\\u03a9'");
+        assertEquals("\\u03a9", c.getValue());
+    }
+
+    @Test
+    void parseUnicodeEscapedEscape() {
+        JavaParser javaParser = new JavaParser(new ParserConfiguration()
+                .setPreprocessUnicodeEscapes(true));
+
+        CharLiteralExpr c = javaParser.parse(ParseStart.EXPRESSION, provider("'\\u005c''")).getResult().get().asCharLiteralExpr();
+        assertEquals("\\'", c.getValue());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/DoubleLiteralExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/DoubleLiteralExprTest.java
new file mode 100644
index 0000000..663242c
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/DoubleLiteralExprTest.java
@@ -0,0 +1,43 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+
+class DoubleLiteralExprTest {
+    @Test
+    void test1() {
+        float x = 0x0.00_00_02p-126f;
+        DoubleLiteralExpr e = parseExpression("0x0.00_00_02p-126f");
+        Assertions.assertEquals(x, e.asDouble());
+    }
+
+    @Test
+    void test2() {
+        double x = 0x0.000_000_000_000_1p-1_022;
+        DoubleLiteralExpr e = parseExpression("0x0.000_000_000_000_1p-1_022");
+        Assertions.assertEquals(x, e.asDouble());
+    }
+
+    @Test
+    void test3() {
+        double a = 0x1.p+1;
+        DoubleLiteralExpr e = parseExpression("0x1.p+1");
+        Assertions.assertEquals(a, e.asDouble());
+    }
+
+    @Test
+    void test4() {
+        double a = 0x.0p0;
+        DoubleLiteralExpr e = parseExpression("0x.0p0");
+        Assertions.assertEquals(a, e.asDouble());
+    }
+
+    @Test
+    void test5() {
+        double x = 0x0_0.0_0p-1_0;
+        DoubleLiteralExpr e = parseExpression("0x0_0.0_0p-1_0");
+        Assertions.assertEquals(x, e.asDouble());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/InstanceOfExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/InstanceOfExprTest.java
new file mode 100644
index 0000000..cb14758
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/InstanceOfExprTest.java
@@ -0,0 +1,15 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+
+class InstanceOfExprTest {
+    @Test
+    void annotationsOnTheType() {
+        InstanceOfExpr expr = parseExpression("s instanceof @A @DA String");
+
+        assertThat(expr.getType().getAnnotations()).containsExactly(new MarkerAnnotationExpr("A"), new MarkerAnnotationExpr("DA"));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/LambdaExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/LambdaExprTest.java
new file mode 100644
index 0000000..6683c0e
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/LambdaExprTest.java
@@ -0,0 +1,76 @@
+package com.github.javaparser.ast.expr;
+
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.type.UnknownType;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseBlock;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LambdaExprTest {
+    @Test
+    void lambdaRange1() {
+        Expression expression = parseExpression("x -> y");
+        assertRange("x", "y", expression);
+    }
+
+    @Test
+    void lambdaRange2() {
+        Expression expression = parseExpression("(x) -> y");
+        assertRange("(", "y", expression);
+    }
+
+    private void assertRange(String startToken, String endToken, Node node) {
+        TokenRange tokenRange = node.getTokenRange().get();
+        assertEquals(startToken, tokenRange.getBegin().asString());
+        assertEquals(endToken, tokenRange.getEnd().asString());
+    }
+
+    @Test
+    void getExpressionBody() {
+        LambdaExpr lambdaExpr = parseExpression("x -> y").asLambdaExpr();
+        assertEquals("Optional[y]", lambdaExpr.getExpressionBody().toString());
+    }
+
+    @Test
+    void getNoExpressionBody() {
+        LambdaExpr lambdaExpr = parseExpression("x -> {y;}").asLambdaExpr();
+        assertEquals("Optional.empty", lambdaExpr.getExpressionBody().toString());
+    }
+
+    @Test
+    void oneParameterAndExpressionUtilityConstructor() {
+        LambdaExpr expr = new LambdaExpr(new Parameter(new UnknownType(), "a"), parseExpression("5"));
+        assertEquals("a -> 5", expr.toString());
+    }
+
+    @Test
+    void oneParameterAndStatementUtilityConstructor() {
+        LambdaExpr expr = new LambdaExpr(new Parameter(new UnknownType(), "a"), parseBlock("{return 5;}"));
+        assertEqualsNoEol("a -> {\n    return 5;\n}", expr.toString());
+    }
+
+    @Test
+    void multipleParametersAndExpressionUtilityConstructor() {
+        LambdaExpr expr = new LambdaExpr(new NodeList<>(new Parameter(new UnknownType(), "a"), new Parameter(new UnknownType(), "b")), parseExpression("5"));
+        assertEquals("(a, b) -> 5", expr.toString());
+    }
+
+    @Test
+    void multipleParametersAndStatementUtilityConstructor() {
+        LambdaExpr expr = new LambdaExpr(new NodeList<>(new Parameter(new UnknownType(), "a"), new Parameter(new UnknownType(), "b")), parseBlock("{return 5;}"));
+        assertEqualsNoEol("(a, b) -> {\n    return 5;\n}", expr.toString());
+    }
+
+    @Test
+    void zeroParametersAndStatementUtilityConstructor() {
+        LambdaExpr expr = new LambdaExpr(new NodeList<>(), parseBlock("{return 5;}"));
+        assertEqualsNoEol("() -> {\n    return 5;\n}", expr.toString());
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/LiteralStringValueExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/LiteralStringValueExprTest.java
new file mode 100644
index 0000000..77a7985
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/LiteralStringValueExprTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2017 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.expr;
+
+import org.assertj.core.data.Percentage;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SuppressWarnings("OctalInteger")
+class LiteralStringValueExprTest {
+
+    @Test
+    void trivialLiteralsAreConverted() {
+        assertThat(new CharLiteralExpr('\t').getValue()).isEqualTo("\\t");
+        assertThat(new CharLiteralExpr('\b').getValue()).isEqualTo("\\b");
+        assertThat(new CharLiteralExpr('\f').getValue()).isEqualTo("\\f");
+        assertThat(new CharLiteralExpr('\r').getValue()).isEqualTo("\\r");
+        assertThat(new CharLiteralExpr('\n').getValue()).isEqualTo("\\n");
+        assertThat(new CharLiteralExpr('\\').getValue()).isEqualTo("\\\\");
+        assertThat(new CharLiteralExpr('\"').getValue()).isEqualTo("\\\"");
+
+        assertThat(new IntegerLiteralExpr("0B0").asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr("0b0").asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr("0X0").asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr("0x0").asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr(0).asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr(00).asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr(0B0).asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr(0b0).asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr(0X0).asInt()).isEqualTo(0);
+        assertThat(new IntegerLiteralExpr(0x0).asInt()).isEqualTo(0);
+
+        assertThat(new LongLiteralExpr("0B0L").asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr("0b0L").asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr("0X0L").asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr("0x0L").asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr(0L).asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr(00L).asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr(0B0L).asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr(0b0L).asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr(0X0L).asLong()).isEqualTo(0);
+        assertThat(new LongLiteralExpr(0x0L).asLong()).isEqualTo(0);
+
+        assertThat(new DoubleLiteralExpr("0.0f").asDouble()).isEqualTo(0.0);
+        assertThat(new DoubleLiteralExpr("0.0F").asDouble()).isEqualTo(0.0);
+        assertThat(new DoubleLiteralExpr("0.0d").asDouble()).isEqualTo(0.0);
+        assertThat(new DoubleLiteralExpr("0.0D").asDouble()).isEqualTo(0.0);
+        assertThat(new DoubleLiteralExpr(0.0F).asDouble()).isEqualTo(0.0);
+        assertThat(new DoubleLiteralExpr(0.0f).asDouble()).isEqualTo(0.0);
+        assertThat(new DoubleLiteralExpr(0.0D).asDouble()).isEqualTo(0.0);
+        assertThat(new DoubleLiteralExpr(0.0d).asDouble()).isEqualTo(0.0);
+    }
+
+    @Test
+    void lowerAndUpperBoundIntegersAreConverted() {
+        IntegerLiteralExpr dec = parseExpression("2147483647");
+        IntegerLiteralExpr posOct = parseExpression("0177_7777_7777");
+        IntegerLiteralExpr negOct = parseExpression("0377_7777_7777");
+        IntegerLiteralExpr posHex = parseExpression("0x7fff_ffff");
+        IntegerLiteralExpr negHex = parseExpression("0xffff_ffff");
+        IntegerLiteralExpr posBin = parseExpression("0b0111_1111_1111_1111_1111_1111_1111_1111");
+        IntegerLiteralExpr negBin = parseExpression("0b1000_0000_0000_0000_0000_0000_0000_0000");
+
+        assertThat(dec.asInt()).isEqualTo(2147483647);
+        assertThat(posOct.asInt()).isEqualTo(2147483647); // 0177_7777_7777
+        assertThat(negOct.asInt()).isEqualTo(-1); // 0377_7777_7777
+        assertThat(posHex.asInt()).isEqualTo(0x7fff_ffff);
+        assertThat(negHex.asInt()).isEqualTo(0xffff_ffff);
+        assertThat(posBin.asInt()).isEqualTo(0b0111_1111_1111_1111_1111_1111_1111_1111);
+        assertThat(negBin.asInt()).isEqualTo(0b1000_0000_0000_0000_0000_0000_0000_0000);
+    }
+
+    @Test
+    void lowerAndUpperBoundLongsAreConverted() {
+        LongLiteralExpr dec = parseExpression("9223372036854775807L");
+        LongLiteralExpr posOct = parseExpression("07_7777_7777_7777_7777_7777L");
+        LongLiteralExpr negOct = parseExpression("010_0000_0000_0000_0000_0000L");
+        LongLiteralExpr posHex = parseExpression("0x7fff_ffff_ffff_ffffL");
+        LongLiteralExpr negHex = parseExpression("0xffff_ffff_ffff_ffffL");
+        LongLiteralExpr posBin = parseExpression("0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L");
+        LongLiteralExpr negBin = parseExpression("0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L");
+
+        assertThat(dec.asLong()).isEqualTo(9223372036854775807L);
+        assertThat(posOct.asLong()).isEqualTo(9223372036854775807L); // 07_7777_7777_7777_7777_7777L
+        assertThat(negOct.asLong()).isEqualTo(-9223372036854775808L); // 010_0000_0000_0000_0000_0000L
+        assertThat(posHex.asLong()).isEqualTo(0x7fff_ffff_ffff_ffffL);
+        assertThat(negHex.asLong()).isEqualTo(0xffff_ffff_ffff_ffffL);
+        assertThat(posBin.asLong()).isEqualTo(0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L);
+        assertThat(negBin.asLong()).isEqualTo(0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L);
+    }
+
+    @Test
+    void charLiteralsAreConverted() {
+        CharLiteralExpr a = parseExpression("'a'");
+        CharLiteralExpr percent = parseExpression("'%'");
+        CharLiteralExpr tab = parseExpression("'\\t'");
+        CharLiteralExpr newLine = parseExpression("'\\n'");
+        CharLiteralExpr slash = parseExpression("'\\\\'");
+        CharLiteralExpr quote = parseExpression("'\\''");
+        CharLiteralExpr omega = parseExpression("'\\u03a9'");
+        CharLiteralExpr unicode = parseExpression("'\\uFFFF'");
+        CharLiteralExpr ascii = parseExpression("'\\177'");
+        CharLiteralExpr trademark = parseExpression("'™'");
+
+        assertThat(a.asChar()).isEqualTo('a');
+        assertThat(percent.asChar()).isEqualTo('%');
+        assertThat(tab.asChar()).isEqualTo('\t');
+        assertThat(newLine.asChar()).isEqualTo('\n');
+        assertThat(slash.asChar()).isEqualTo('\\');
+        assertThat(quote.asChar()).isEqualTo('\'');
+        assertThat(omega.asChar()).isEqualTo('\u03a9');
+        assertThat(unicode.asChar()).isEqualTo('\uFFFF');
+        assertThat(ascii.asChar()).isEqualTo('\177');
+        assertThat(trademark.asChar()).isEqualTo('™');
+    }
+
+    @Test
+    void lowerAndUpperBoundDoublesAreConverted() {
+        DoubleLiteralExpr posFloat = parseExpression("3.4028235e38f");
+        DoubleLiteralExpr negFloat = parseExpression("1.40e-45f");
+        DoubleLiteralExpr posDouble = parseExpression("1.7976931348623157e308");
+        DoubleLiteralExpr negDouble = parseExpression("4.9e-324");
+        DoubleLiteralExpr posHexFloat = parseExpression("0x1.fffffffffffffp1023");
+        DoubleLiteralExpr negHexFloat = parseExpression("0x0.0000000000001P-1022");
+
+        assertThat(posFloat.asDouble()).isCloseTo(3.4028235e38f, Percentage.withPercentage(1));
+        assertThat(negFloat.asDouble()).isCloseTo(1.40e-45f, Percentage.withPercentage(1));
+        assertThat(posDouble.asDouble()).isEqualTo(1.7976931348623157e308);
+        assertThat(negDouble.asDouble()).isEqualTo(4.9e-324);
+        assertThat(posHexFloat.asDouble()).isEqualTo(0x1.fffffffffffffp1023);
+        assertThat(negHexFloat.asDouble()).isEqualTo(0x0.0000000000001P-1022);
+    }
+
+    @Test
+    void specialCharactersInStringsAreEscaped() {
+        assertThat(new StringLiteralExpr("\n").getValue()).isEqualTo("\\n");
+        assertThat(new StringLiteralExpr("\r").getValue()).isEqualTo("\\r");
+        assertThat(new StringLiteralExpr("").setEscapedValue("\n").getValue()).isEqualTo("\\n");
+        assertThat(new StringLiteralExpr("").setEscapedValue("\r").getValue()).isEqualTo("\\r");
+        assertThat(new StringLiteralExpr("").setEscapedValue("\n").asString()).isEqualTo("\n");
+        assertThat(new StringLiteralExpr("").setEscapedValue("\r").asString()).isEqualTo("\r");
+        assertThat(new StringLiteralExpr("Hello\nWorld\rHello\"World\'").asString()).isEqualTo("Hello\nWorld\rHello\"World\'");
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/MethodCallExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/MethodCallExprTest.java
new file mode 100644
index 0000000..9610a1f
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/MethodCallExprTest.java
@@ -0,0 +1,22 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static java.util.Optional.empty;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MethodCallExprTest {
+    
+    @Test
+    void replaceLambdaIssue1290() {
+        MethodCallExpr methodCallExpr = parseExpression("callSomeFun(r -> r instanceof SomeType)").asMethodCallExpr();
+        LambdaExpr lambdaExpr = methodCallExpr.getArgument(0).asLambdaExpr();
+        MethodCallExpr lambdaWrapper = new MethodCallExpr("lambdaWrapper");
+        lambdaExpr.replace(lambdaWrapper);
+        
+        assertEquals(2, methodCallExpr.getChildNodes().size());
+        assertEquals(empty(), lambdaExpr.getParentNode());
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/MethodReferenceExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/MethodReferenceExprTest.java
new file mode 100644
index 0000000..92eb9a3
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/MethodReferenceExprTest.java
@@ -0,0 +1,115 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.TestUtils.assertExpressionValid;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class MethodReferenceExprTest {
+
+    @Test
+    void methodReferenceExprHasAlwaysAScope() {
+        assertNotNull(new MethodReferenceExpr().getScope());
+    }
+
+    @Test
+    void reference1() {
+        assertExpressionValid("String::length");
+    }
+        
+    @Test
+    void reference2() {
+        assertExpressionValid("System::currentTimeMillis // static method");
+    }
+        
+    @Test
+    void reference3() {
+        assertExpressionValid("List<String>::size // explicit type arguments for generic type");
+    }
+        
+    @Test
+    void reference4() {
+        assertExpressionValid("List::size // inferred type arguments for generic type");
+    }
+        
+    @Test
+    void reference5() {
+        assertExpressionValid("int[]::clone");
+    }
+        
+    @Test
+    void reference6() {
+        assertExpressionValid("T::tvarMember");
+    }
+        
+    @Test
+    void reference7() {
+        assertExpressionValid("System.out::println");
+    }
+        
+    @Test
+    void reference8() {
+        assertExpressionValid("\"abc\"::length");
+    }
+        
+    @Test
+    void reference9() {
+        assertExpressionValid("foo[x]::bar");
+    }
+        
+    @Test
+    void reference10() {
+        assertExpressionValid("(test ? list.replaceAll(String::trim) : list) :: iterator");
+    }
+        
+    @Test
+    void reference10Annotated1() {
+        assertExpressionValid("(test ? list.replaceAll(@A String::trim) : list) :: iterator");
+    }
+        
+    @Test
+    void reference11() {
+        assertExpressionValid("String::valueOf // overload resolution needed");
+    }
+        
+    @Test
+    void reference12() {
+        assertExpressionValid("Arrays::sort // type arguments inferred from context");
+    }
+        
+    @Test
+    void reference13() {
+        assertExpressionValid("Arrays::<String>sort // explicit type arguments");
+    }
+        
+    @Test
+    void reference14() {
+        assertExpressionValid("ArrayList<String>::new // constructor for parameterized type");
+    }
+        
+    @Test
+    void reference15() {
+        assertExpressionValid("ArrayList::new // inferred type arguments");
+    }
+        
+    @Test
+    void reference16() {
+        assertExpressionValid("Foo::<Integer>new // explicit type arguments");
+    }
+        
+    @Test
+    void reference17() {
+        assertExpressionValid("Bar<String>::<Integer>new // generic class, generic constructor");
+    }
+        
+    @Test
+    void reference18() {
+        assertExpressionValid("Outer.Inner::new // inner class constructor");
+    }
+        
+    @Test
+    void reference19() {
+        assertExpressionValid("int[]::new // array creation");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/NameTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/NameTest.java
new file mode 100644
index 0000000..4eef435
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/NameTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2017 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.expr;
+
+import com.github.javaparser.ParseProblemException;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.ImportDeclaration;
+import com.github.javaparser.printer.ConcreteSyntaxModel;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.*;
+
+class NameTest {
+
+    @Test
+    void outerNameExprIsTheRightMostIdentifier() {
+        Name name = parseName("a.b.c");
+        assertEquals("c", name.getIdentifier());
+    }
+
+    @Test
+    void parsingAndUnparsingWorks() {
+        Name name = parseName("a.b.c");
+        assertEquals("a.b.c", name.asString());
+    }
+
+    @Test
+    void parsingEmptyNameThrowsException() {
+        assertThrows(ParseProblemException.class, () -> parseName(""));
+    }
+
+    @Test
+    void importName() {
+        ImportDeclaration importDeclaration = parseImport("import java.util.List;");
+
+        assertEquals("import java.util.List;" + EOL, importDeclaration.toString());
+        assertEquals("import java.util.List;" , ConcreteSyntaxModel.genericPrettyPrint(importDeclaration));
+    }
+
+    @Test
+    void packageName() {
+        CompilationUnit cu = parse("package p1.p2;");
+
+        assertEquals("package p1.p2;" + EOL + EOL, cu.toString());
+        assertEquals("package p1.p2;" + EOL + EOL, ConcreteSyntaxModel.genericPrettyPrint(cu));
+    }
+
+    @Test
+    void isInternalNegative() {
+        Name name = parseName("a.b.c");
+        assertFalse(name.isInternal());
+    }
+
+    @Test
+    void isInternalPositive() {
+        Name name = parseName("a.b.c");
+        assertTrue(name
+                .getQualifier().get().isInternal());
+        assertTrue(name
+                .getQualifier().get()
+                .getQualifier().get().isInternal());
+    }
+
+    @Test
+    void isTopLevelNegative() {
+        Name name = parseName("a.b.c");
+        assertFalse(name
+                .getQualifier().get().isTopLevel());
+        assertFalse(name
+                .getQualifier().get()
+                .getQualifier().get().isTopLevel());
+    }
+
+    @Test
+    void isTopLevelPositive() {
+        Name name = parseName("a.b.c");
+        assertTrue(name.isTopLevel());
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/ObjectCreationExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/ObjectCreationExprTest.java
new file mode 100644
index 0000000..a350472
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/ObjectCreationExprTest.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.ast.expr;
+
+import com.github.javaparser.utils.TestParser;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ObjectCreationExprTest {
+    @Test
+    void aaa() {
+        Expression e = TestParser.parseExpression("new @Test N()");
+        assertEquals("new @Test N()", e.toString());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SimpleNameTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SimpleNameTest.java
new file mode 100644
index 0000000..458ab91
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SimpleNameTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2017 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.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseSimpleName;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class SimpleNameTest {
+
+    @Test
+    void defaultConstructorSetsIdentifierToEmpty() {
+        assertEquals("empty", new SimpleName().getIdentifier());
+    }
+
+    @Test
+    void identifierMustNotBeEmpty() {
+        assertThrows(AssertionError.class, () -> new SimpleName(""));
+    }
+
+    @Test
+    void identifierMustNotBeNull() {
+        assertThrows(AssertionError.class, () -> new SimpleName(null));
+    }
+
+    @Test
+    void unicodeEscapesArePreservedInIdentifiers() {
+        SimpleName name = parseSimpleName("xxx\\u2122xxx");
+        assertEquals("xxx\\u2122xxx", name.asString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/StringLiteralExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/StringLiteralExprTest.java
new file mode 100644
index 0000000..98b6dd1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/StringLiteralExprTest.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.junit.jupiter.api.Assertions.*;
+
+class StringLiteralExprTest {
+    @Test
+    void unicodeEscapesArePreservedInStrings() {
+        StringLiteralExpr omega = parseExpression("\"xxx\\u03a9xxx\"");
+        assertEquals("xxx\\u03a9xxx", omega.getValue());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SuperExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SuperExprTest.java
new file mode 100644
index 0000000..a443901
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SuperExprTest.java
@@ -0,0 +1,33 @@
+package com.github.javaparser.ast.expr;
+
+import com.github.javaparser.ParseProblemException;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SuperExprTest {
+    @Test
+    void justSuper() {
+        assertThrows(ParseProblemException.class, () -> parseExpression("super"));
+    }
+
+    @Test
+    void singleScopeSuper() {
+        Expression expr = parseExpression("A.super");
+
+        Name className = expr.asSuperExpr().getTypeName().get();
+
+        assertEquals("A", className.asString());
+    }
+
+    @Test
+    void multiScopeSuper() {
+        Expression expr = parseExpression("a.B.super");
+
+        Name className = expr.asSuperExpr().getTypeName().get();
+
+        assertEquals("a.B", className.asString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SwitchExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SwitchExprTest.java
new file mode 100644
index 0000000..01431ad
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/SwitchExprTest.java
@@ -0,0 +1,97 @@
+package com.github.javaparser.ast.expr;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.SwitchEntry;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ast.stmt.SwitchEntry.Type.*;
+import static com.github.javaparser.utils.TestParser.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SwitchExprTest {
+    @Test
+    void jep325Example2() {
+        NodeList<Expression> entry2labels = parseStatement("int numLetters = switch (day) {\n" +
+                "    case MONDAY, FRIDAY, SUNDAY -> 6;\n" +
+                "    case TUESDAY                -> 7;\n" +
+                "    case THURSDAY, SATURDAY     -> 8;\n" +
+                "    case WEDNESDAY              -> 9;\n" +
+                "};").findAll(SwitchEntry.class).get(0).getLabels();
+
+        assertEquals(3, entry2labels.size());
+        assertEquals("MONDAY", entry2labels.get(0).toString());
+        assertEquals("FRIDAY", entry2labels.get(1).toString());
+        assertEquals("SUNDAY", entry2labels.get(2).toString());
+    }
+
+    @Test
+    void funkyExpressions() {
+        parseStatement("int numLetters = switch (day) {\n" +
+                "    case 1+1, 2+2 -> 6;\n" +
+                "    case \"Henk\"-> 7;\n" +
+                "    case ((3)+3)+3 -> 8;\n" +
+                "};");
+    }
+
+    @Test
+    void jep325Example3() {
+        parseBodyDeclaration("static void howMany(int k) {\n" +
+                "    switch (k) {\n" +
+                "        case 1 -> System.out.println(\"one\");\n" +
+                "        case 2 -> System.out.println(\"two\");\n" +
+                "        case 3 -> System.out.println(\"many\");\n" +
+                "    }\n" +
+                "}");
+    }
+
+
+    @Test
+    void aThrowStatement() {
+        SwitchExpr switchExpr = parseExpression("switch (k) {\n" +
+                "        case 1 -> throw new Exception(\"one\");\n" +
+                "    }").findFirst(SwitchExpr.class).get();
+
+        assertEquals(THROWS_STATEMENT, switchExpr.getEntry(0).getType());
+    }
+
+    @Test
+    void jep325Example4() {
+        SwitchExpr switchExpr = parseStatement("T result = switch (arg) {\n" +
+                "    case L1 -> e1;\n" +
+                "    case L2 -> e2;\n" +
+                "    default -> e3;\n" +
+                "};").findFirst(SwitchExpr.class).get();
+
+        assertEquals(EXPRESSION, switchExpr.getEntry(0).getType());
+    }
+
+    @Test
+    void jep325Example5() {
+        SwitchExpr switchExpr = parseStatement("int j = switch (day) {\n" +
+                "    case MONDAY  -> 0;\n" +
+                "    case TUESDAY -> 1;\n" +
+                "    default      -> {\n" +
+                "        int k = day.toString().length();\n" +
+                "        int result = f(k);\n" +
+                "        break result;\n" +
+                "    }\n" +
+                "};").findFirst(SwitchExpr.class).get();
+
+        assertEquals(BLOCK, switchExpr.getEntry(2).getType());
+        assertEquals(BlockStmt.class, switchExpr.getEntry(2).getStatements().get(0).getClass());
+    }
+
+    @Test
+    void jep325Example6() {
+        parseStatement("int result = switch (s) {\n" +
+                "    case \"Foo\": \n" +
+                "        break 1;\n" +
+                "    case \"Bar\":\n" +
+                "        break 2;\n" +
+                "    default:\n" +
+                "        System.out.println(\"Neither Foo nor Bar, hmmm...\");\n" +
+                "        break 0;\n" +
+                "};");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/ThisExprTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/ThisExprTest.java
new file mode 100644
index 0000000..d6b32f3
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/expr/ThisExprTest.java
@@ -0,0 +1,34 @@
+package com.github.javaparser.ast.expr;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class ThisExprTest {
+    @Test
+    void justThis() {
+        Expression expr = parseExpression("this");
+
+        assertTrue(expr.isThisExpr());
+    }
+
+    @Test
+    void singleScopeThis() {
+        Expression expr = parseExpression("A.this");
+
+        Name className = expr.asThisExpr().getTypeName().get();
+
+        assertEquals("A", className.asString());
+    }
+
+    @Test
+    void multiScopeThis() {
+        Expression expr = parseExpression("a.B.this");
+
+        Name className = expr.asThisExpr().getTypeName().get();
+
+        assertEquals("a.B", className.asString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/imports/ImportDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/imports/ImportDeclarationTest.java
new file mode 100644
index 0000000..7570c67
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/imports/ImportDeclarationTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.imports;
+
+import com.github.javaparser.ast.ImportDeclaration;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseImport;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ImportDeclarationTest {
+    @Test
+    void singleTypeImportDeclaration() {
+        ImportDeclaration i = parseImport("import a.b.c.X;");
+        assertEquals("a.b.c.X", i.getNameAsString());
+    }
+
+    @Test
+    void typeImportOnDemandDeclaration() {
+        ImportDeclaration i = parseImport("import a.b.c.D.*;");
+        assertEquals("a.b.c.D", i.getName().toString());
+        assertEquals("D", i.getName().getIdentifier());
+    }
+
+    @Test
+    void singleStaticImportDeclaration() {
+        ImportDeclaration i = parseImport("import static a.b.c.X.def;");
+        assertEquals("a.b.c.X", i.getName().getQualifier().get().asString());
+        assertEquals("def", i.getName().getIdentifier());
+    }
+
+    @Test
+    void staticImportOnDemandDeclaration() {
+        ImportDeclaration i = parseImport("import static a.b.c.X.*;");
+        assertEquals("a.b.c.X", i.getNameAsString());
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithBodyTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithBodyTest.java
new file mode 100644
index 0000000..d2ef9a0
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithBodyTest.java
@@ -0,0 +1,39 @@
+package com.github.javaparser.ast.nodeTypes;
+
+import com.github.javaparser.ast.stmt.ForStmt;
+import com.github.javaparser.ast.stmt.IfStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.utils.TestParser;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class NodeWithBodyTest {
+    @Test
+    void emptyStatementIsEmpty() {
+        ForStmt forStmt = TestParser.parseStatement("for(;;);").asForStmt();
+
+        assertTrue(forStmt.hasEmptyBody());
+    }
+
+    @Test
+    void emptyBlockIsEmpty() {
+        ForStmt forStmt = TestParser.parseStatement("for(;;){}").asForStmt();
+
+        assertTrue(forStmt.hasEmptyBody());
+    }
+
+    @Test
+    void simpleStatementIsNotEmpty() {
+        ForStmt forStmt = TestParser.parseStatement("for(;;)a=b;").asForStmt();
+
+        assertFalse(forStmt.hasEmptyBody());
+    }
+
+    @Test
+    void nonEmptyBlockIsNotEmpty() {
+        ForStmt forStmt = TestParser.parseStatement("for(;;){a=b;}").asForStmt();
+
+        assertFalse(forStmt.hasEmptyBody());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadocTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadocTest.java
new file mode 100644
index 0000000..9967528
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadocTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2017 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.nodeTypes;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.comments.JavadocComment;
+import com.github.javaparser.ast.comments.LineComment;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class NodeWithJavadocTest {
+
+    @Test
+    void removeJavaDocNegativeCaseNoComment() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        assertFalse(decl.removeJavaDocComment());
+    }
+
+    @Test
+    void removeJavaDocNegativeCaseCommentNotJavaDoc() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.setComment(new LineComment("A comment"));
+        assertFalse(decl.removeJavaDocComment());
+        assertTrue(decl.getComment().isPresent());
+    }
+
+    @Test
+    void removeJavaDocPositiveCase() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.setComment(new JavadocComment("A comment"));
+        assertTrue(decl.removeJavaDocComment());
+        assertFalse(decl.getComment().isPresent());
+    }
+
+    @Test
+    void getJavadocOnMethodWithLineCommentShouldReturnEmptyOptional() {
+        MethodDeclaration method = new MethodDeclaration();
+        method.setLineComment("Lorem Ipsum.");
+
+        assertFalse(method.getJavadocComment().isPresent());
+        assertFalse(method.getJavadoc().isPresent());
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiersTest.java
new file mode 100644
index 0000000..a50bbed
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiersTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2017 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.nodeTypes;
+
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.observer.AstObserverAdapter;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import org.junit.jupiter.api.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.github.javaparser.ast.Modifier.Keyword.PRIVATE;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.Keyword.STATIC;
+import static com.github.javaparser.ast.Modifier.Keyword.SYNCHRONIZED;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class NodeWithModifiersTest {
+
+    @Test
+    void addModifierWorks() {
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.addModifier(PUBLIC);
+        assertEquals(createModifierList(PUBLIC), decl.getModifiers());
+    }
+
+    @Test
+    void addModifierTriggerNotification() {
+        List<String> changes = new LinkedList<>();
+        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(new NodeList<>(),
+                false, "Foo");
+        decl.register(new AstObserverAdapter() {
+            @Override
+            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add("property " + property.name() + " is changed to " + newValue);
+            }
+        });
+        decl.addModifier(PUBLIC);
+        assertEquals(1, changes.size());
+        assertEquals("property MODIFIERS is changed to [public ]", changes.get(0));
+    }
+
+    @Test
+    void removeExistingModifier() {
+        NodeWithModifiers node = anythingWithModifiers(PUBLIC);
+        node.removeModifier(PUBLIC);
+        assertEquals(0, node.getModifiers().size());
+    }
+
+    @Test
+    void ignoreNotExistingModifiersOnRemove() {
+        NodeWithModifiers node = anythingWithModifiers(PUBLIC);
+        node.removeModifier(PRIVATE);
+
+        assertEquals(createModifierList(PUBLIC), node.getModifiers());
+    }
+
+    @Test
+    void keepModifiersThatShouldNotBeRemoved() {
+        NodeWithModifiers node = anythingWithModifiers(PUBLIC, STATIC, SYNCHRONIZED);
+        node.removeModifier(PUBLIC, PRIVATE, STATIC);
+
+        assertEquals(createModifierList(SYNCHRONIZED), node.getModifiers());
+    }
+
+    private NodeWithModifiers anythingWithModifiers(Modifier.Keyword ... keywords) {
+        ClassOrInterfaceDeclaration foo = new ClassOrInterfaceDeclaration(new NodeList<>(), false, "Foo");
+        foo.addModifier(keywords);
+        return foo;
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithOptionalScopeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithOptionalScopeTest.java
new file mode 100644
index 0000000..03661e0
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithOptionalScopeTest.java
@@ -0,0 +1,28 @@
+package com.github.javaparser.ast.nodeTypes;
+
+import com.github.javaparser.ast.expr.*;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NodeWithOptionalScopeTest {
+
+    @Test
+    void commonExpressionWhichHaveInterfaceNodeWithOptionalScope() {
+        NodeWithOptionalScope methodCallExpr = new MethodCallExpr(new NameExpr("A"), "call");
+        NodeWithOptionalScope objectCreationExpr = new ObjectCreationExpr();
+
+        assertTrue(methodCallExpr.getScope().isPresent());
+        assertFalse(objectCreationExpr.getScope().isPresent());
+    }
+
+    @Test
+    void removeScope() {
+        MethodCallExpr methodCallExpr = new MethodCallExpr(new NameExpr("A"), "method");
+
+        methodCallExpr.removeScope();
+
+        assertFalse(methodCallExpr.getScope().isPresent());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithTraversableScopeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithTraversableScopeTest.java
new file mode 100644
index 0000000..2b86d71
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithTraversableScopeTest.java
@@ -0,0 +1,23 @@
+package com.github.javaparser.ast.nodeTypes;
+
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+class NodeWithTraversableScopeTest {
+    @Test
+    void traverse1() {
+        NodeWithTraversableScope expression = parseExpression("getAddress().name.startsWith(\"abc\")");
+
+        assertInstanceOf(MethodCallExpr.class, expression);
+        expression = (NodeWithTraversableScope) expression.traverseScope().get();
+        assertInstanceOf(FieldAccessExpr.class, expression);
+        expression = (NodeWithTraversableScope) expression.traverseScope().get();
+        assertInstanceOf(MethodCallExpr.class, expression);
+        assertFalse(expression.traverseScope().isPresent());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithVariablesTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithVariablesTest.java
new file mode 100644
index 0000000..0c8e373
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithVariablesTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.type.PrimitiveType;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseVariableDeclarationExpr;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class NodeWithVariablesTest {
+
+    @Test
+    void getCommonTypeWorksForNormalVariables() {
+        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
+        assertEquals(PrimitiveType.intType(), declaration.getCommonType());
+    }
+
+    @Test
+    void getCommonTypeWorksForArrayTypes() {
+        parseVariableDeclarationExpr("int a[],b[]").getCommonType();
+    }
+
+    @Test
+    void getCommonTypeFailsOnArrayDifferences() {
+        assertThrows(AssertionError.class, () -> parseVariableDeclarationExpr("int a[],b[][]").getCommonType());
+    }
+
+    @Test
+    void getCommonTypeFailsOnDodgySetterUsage() {
+        assertThrows(AssertionError.class, () -> {
+            VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
+            declaration.getVariable(1).setType(String.class);
+            declaration.getCommonType();
+        });
+    }
+
+    @Test
+    void getCommonTypeFailsOnInvalidEmptyVariableList() {
+        assertThrows(AssertionError.class, () -> {
+            VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a");
+            declaration.getVariables().clear();
+            declaration.getCommonType();
+        });
+    }
+
+    @Test
+    void getElementTypeWorksForNormalVariables() {
+        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
+        assertEquals(PrimitiveType.intType(), declaration.getElementType());
+    }
+
+    @Test
+    void getElementTypeWorksForArrayTypes() {
+        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a[],b[]");
+        assertEquals(PrimitiveType.intType(), declaration.getElementType());
+    }
+
+    @Test
+    void getElementTypeIsOkayWithArrayDifferences() {
+        parseVariableDeclarationExpr("int a[],b[][]").getElementType();
+    }
+
+    @Test
+    void getElementTypeFailsOnDodgySetterUsage() {
+        assertThrows(AssertionError.class, () -> {
+            VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
+            declaration.getVariable(1).setType(String.class);
+            declaration.getElementType();
+        });
+    }
+
+    @Test
+    void getElementTypeFailsOnInvalidEmptyVariableList() {
+        assertThrows(AssertionError.class, () -> {
+            VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a");
+            declaration.getVariables().clear();
+            declaration.getElementType();
+        });
+    }
+
+    @Test
+    void setAllTypesWorks() {
+        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int[] a[],b[][]");
+        declaration.setAllTypes(StaticJavaParser.parseType("Dog"));
+        assertEquals("Dog a, b", declaration.toString());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/observer/PropagatingAstObserverTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/observer/PropagatingAstObserverTest.java
new file mode 100644
index 0000000..f1ab1c4
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/observer/PropagatingAstObserverTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.observer;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class PropagatingAstObserverTest {
+    @Test
+    void verifyPropagation() {
+        String code = "class A {  }";
+        CompilationUnit cu = parse(code);
+        List<String> changes = new ArrayList<>();
+        AstObserver observer = new PropagatingAstObserver() {
+            @Override
+            public void concretePropertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
+            }
+        };
+        cu.registerForSubtree(observer);
+
+        assertEquals(Arrays.asList(), changes);
+
+        FieldDeclaration fieldDeclaration = cu.getClassByName("A").get().addField("String", "foo");
+        assertEquals(Arrays.asList(), changes);
+        assertTrue(fieldDeclaration.isRegistered(observer));
+
+        cu.getClassByName("A").get().getFieldByName("foo").get().getVariables().get(0).setName("Bar");
+        assertEquals(Arrays.asList("VariableDeclarator.name changed from foo to Bar"), changes);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/BreakStmtTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/BreakStmtTest.java
new file mode 100644
index 0000000..1c00382
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/BreakStmtTest.java
@@ -0,0 +1,29 @@
+package com.github.javaparser.ast.stmt;
+
+import com.github.javaparser.ast.expr.BinaryExpr;
+import com.github.javaparser.utils.TestParser;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+class BreakStmtTest {
+    @Test
+    void simpleBreak() {
+        BreakStmt statement = TestParser.parseStatement("break;").asBreakStmt();
+        assertFalse(statement.getValue().isPresent());
+    }
+
+    @Test
+    void breakWithLabel() {
+        BreakStmt statement = TestParser.parseStatement("break hond;").asBreakStmt();
+        assertEquals("hond", statement.getValue().get().asNameExpr().getName().asString());
+
+    }
+
+    @Test
+    void breakWithExpression() {
+        BreakStmt statement = TestParser.parseStatement("break 12*12;").asBreakStmt();
+        assertEquals(BinaryExpr.class, statement.getValue().get().getClass());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/ForEachStmtTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/ForEachStmtTest.java
new file mode 100644
index 0000000..eda3866
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/ForEachStmtTest.java
@@ -0,0 +1,26 @@
+package com.github.javaparser.ast.stmt;
+
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.type.PrimitiveType;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+import static org.junit.jupiter.api.Assertions.*;
+
+class ForEachStmtTest {
+    @Test
+    void nonFinalPrimitive() {
+        ForEachStmt statement = parseStatement("for (int i : ints) {}").asForEachStmt();
+        assertFalse(statement.hasFinalVariable());
+        assertEquals(PrimitiveType.intType(), statement.getVariableDeclarator().getType());
+        assertEquals("i", statement.getVariableDeclarator().getName().getIdentifier());
+    }
+
+    @Test
+    void finalNonPrimitive() {
+        ForEachStmt statement = parseStatement("for (final Object o : objs) {}").asForEachStmt();
+        assertTrue(statement.hasFinalVariable());
+        assertEquals(new ClassOrInterfaceType(null, "Object"), statement.getVariableDeclarator().getType());
+        assertEquals("o", statement.getVariableDeclarator().getName().getIdentifier());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/IfElseStmtTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/IfElseStmtTest.java
new file mode 100644
index 0000000..afbf945
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/IfElseStmtTest.java
@@ -0,0 +1,35 @@
+package com.github.javaparser.ast.stmt;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class IfElseStmtTest {
+
+    @Test
+    void issue1247withElseSingleStmt() {
+        IfStmt ifStmt = parseStatement("if (cond) doSomething(); else doSomethingElse();").asIfStmt();
+        assertFalse(ifStmt.hasElseBlock());
+        assertTrue(ifStmt.hasElseBranch());
+        assertFalse(ifStmt.hasCascadingIfStmt());
+    }
+
+    @Test
+    void issue1247withElseBlockStmt() {
+        IfStmt ifStmt = parseStatement("if (cond) doSomething(); else { doSomethingElse(); }").asIfStmt();
+        assertTrue(ifStmt.hasElseBlock());
+        assertTrue(ifStmt.hasElseBranch());
+        assertFalse(ifStmt.hasCascadingIfStmt());
+    }
+
+    @Test
+    void issue1247withElseSingleStmtWhichIsAnIf() {
+        IfStmt ifStmt = parseStatement("if (cond1) doSomething(); else if (cond2) doSomethingElse();").asIfStmt();
+        assertFalse(ifStmt.hasElseBlock());
+        assertTrue(ifStmt.hasElseBranch());
+        assertTrue(ifStmt.hasCascadingIfStmt());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/SwitchStmtTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/SwitchStmtTest.java
new file mode 100644
index 0000000..62f3de1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/SwitchStmtTest.java
@@ -0,0 +1,39 @@
+package com.github.javaparser.ast.stmt;
+
+import com.github.javaparser.ast.NodeList;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+import static com.github.javaparser.ast.stmt.SwitchEntry.Type.EXPRESSION;
+import static com.github.javaparser.ast.stmt.SwitchEntry.Type.STATEMENT_GROUP;
+import static org.junit.jupiter.api.Assertions.*;
+
+class SwitchStmtTest {
+    @Test
+    void classicSwitch() {
+        SwitchStmt switchStmt = parseStatement("switch (day) {\n" +
+                "    case TUESDAY: System.out.println(7); break;\n" +
+                "    case FRIDAY: System.out.println(8); break;\n" +
+                "    default: System.out.println(-1); \n" +
+                "}").asSwitchStmt();
+
+        assertEquals(STATEMENT_GROUP, switchStmt.getEntry(0).getType());
+        assertEquals(STATEMENT_GROUP, switchStmt.getEntry(1).getType());
+        assertEquals(STATEMENT_GROUP, switchStmt.getEntry(2).getType());
+        assertEquals(new NodeList<>(), switchStmt.getEntry(2).getLabels());
+    }
+    @Test
+    void jep325Example1() {
+        SwitchStmt switchStmt = parseStatement("switch (day) {\n" +
+//                "    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);\n" +
+                "    case TUESDAY                -> System.out.println(7);\n" +
+//                "    case THURSDAY, SATURDAY     -> System.out.println(8);\n" +
+                "    case WEDNESDAY              -> System.out.println(9);\n" +
+                "}").asSwitchStmt();
+
+        assertEquals(EXPRESSION, switchStmt.getEntry(0).getType());
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/TryStmtTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/TryStmtTest.java
new file mode 100644
index 0000000..d06dc5f
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/stmt/TryStmtTest.java
@@ -0,0 +1,80 @@
+package com.github.javaparser.ast.stmt;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class TryStmtTest {
+    @Test
+    void simpleTest() {
+        TryStmt tryStmt = parse9("try(Reader x = new FileReader()){}");
+        assertInstanceOf(VariableDeclarationExpr.class, tryStmt.getResources().get(0));
+    }
+
+    @Test
+    void multipleTest() {
+        TryStmt tryStmt = parse9("try(Reader x = new FileReader(); Reader x = new FileReader()){}");
+        assertInstanceOf(VariableDeclarationExpr.class, tryStmt.getResources().get(0));
+
+    }
+
+    @Test
+    void modifiersTest() {
+        TryStmt tryStmt = parse9("try(final @A Reader x = new FileReader()){}");
+        assertInstanceOf(VariableDeclarationExpr.class, tryStmt.getResources().get(0));
+
+    }
+
+    @Test
+    void simpleVariable() {
+        TryStmt tryStmt = parse9("try(a){}");
+        assertInstanceOf(NameExpr.class, tryStmt.getResources().get(0));
+
+    }
+
+    @Test
+    void twoSimpleVariables() {
+        TryStmt tryStmt = parse9("try(a;b){}");
+        assertInstanceOf(NameExpr.class, tryStmt.getResources().get(0));
+        assertInstanceOf(NameExpr.class, tryStmt.getResources().get(1));
+
+    }
+
+    @Test
+    void complexVariable() {
+        TryStmt tryStmt = parse9("try(a.b.c){}");
+        assertInstanceOf(FieldAccessExpr.class, tryStmt.getResources().get(0));
+
+    }
+
+    @Test
+    void superAccess() {
+        TryStmt tryStmt = parse9("try(super.a){}");
+        assertInstanceOf(FieldAccessExpr.class, tryStmt.getResources().get(0));
+
+    }
+
+    @Test
+    void outerClassAccess() {
+        TryStmt tryStmt = parse9("try(X.this.a){}");
+        assertInstanceOf(FieldAccessExpr.class, tryStmt.getResources().get(0));
+
+    }
+
+    private <T> T parse9(String code) {
+        JavaParser parser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
+        ParseResult<Statement> result = parser.parse(ParseStart.STATEMENT, provider(code));
+        assertTrue(result.isSuccessful(), result.toString());
+        return (T) result.getResult().get();
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/type/ArrayTypeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/type/ArrayTypeTest.java
new file mode 100644
index 0000000..2a09242
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/type/ArrayTypeTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.expr.ArrayCreationExpr;
+import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.printer.ConcreteSyntaxModel;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ArrayTypeTest {
+    @Test
+    void getFieldDeclarationWithArrays() {
+        FieldDeclaration fieldDeclaration = parseBodyDeclaration("@C int @A[] @B[] a @X[] @Y[];").asFieldDeclaration();
+
+        ArrayType arrayType1 = fieldDeclaration.getVariable(0).getType().asArrayType();
+        ArrayType arrayType2 = arrayType1.getComponentType().asArrayType();
+        ArrayType arrayType3 = arrayType2.getComponentType().asArrayType();
+        ArrayType arrayType4 = arrayType3.getComponentType().asArrayType();
+        PrimitiveType elementType = arrayType4.getComponentType().asPrimitiveType();
+
+        assertThat(arrayType1.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
+        assertThat(arrayType2.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
+        assertThat(arrayType3.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("X")));
+        assertThat(arrayType4.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("Y")));
+
+        assertThat(elementType.getType()).isEqualTo(PrimitiveType.Primitive.INT);
+        assertThat(fieldDeclaration.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
+
+        assertThat(arrayType1.getParentNode().get().getParentNode().get()).isSameAs(fieldDeclaration);
+    }
+
+    @Test
+    void getVariableDeclarationWithArrays() {
+        ExpressionStmt variableDeclarationStatement = parseStatement("@C int @A[] @B[] a @X[] @Y[];").asExpressionStmt();
+        VariableDeclarationExpr variableDeclarationExpr = variableDeclarationStatement.getExpression().asVariableDeclarationExpr();
+
+        ArrayType arrayType1 = variableDeclarationExpr.getVariable(0).getType().asArrayType();
+        ArrayType arrayType2 = arrayType1.getComponentType().asArrayType();
+        ArrayType arrayType3 = arrayType2.getComponentType().asArrayType();
+        ArrayType arrayType4 = arrayType3.getComponentType().asArrayType();
+        PrimitiveType elementType = arrayType4.getComponentType().asPrimitiveType();
+
+        assertThat(arrayType1.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
+        assertThat(arrayType2.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
+        assertThat(arrayType3.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("X")));
+        assertThat(arrayType4.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("Y")));
+
+        assertThat(elementType.getType()).isEqualTo(PrimitiveType.Primitive.INT);
+        assertThat(variableDeclarationExpr.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
+
+        assertThat(arrayType1.getParentNode().get().getParentNode().get()).isSameAs(variableDeclarationExpr);
+    }
+
+    @Test
+    void getMethodDeclarationWithArrays() {
+        MethodDeclaration methodDeclaration = parseBodyDeclaration("@C int @A[] a() @B[] {}").asMethodDeclaration();
+
+        ArrayType arrayType1 = methodDeclaration.getType().asArrayType();
+        ArrayType arrayType2 = arrayType1.getComponentType().asArrayType();
+        Type elementType = arrayType2.getComponentType();
+        assertThat(elementType).isInstanceOf(PrimitiveType.class);
+
+        assertThat(arrayType1.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
+        assertThat(arrayType2.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
+        assertThat(methodDeclaration.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
+
+        assertThat(methodDeclaration.getType().getParentNode().get()).isSameAs(methodDeclaration);
+    }
+
+    @Test
+    void getParameterWithArrays() {
+        MethodDeclaration methodDeclaration = parseBodyDeclaration("void a(@C int @A[] a @B[]) {}").asMethodDeclaration();
+
+        Parameter parameter = methodDeclaration.getParameter(0);
+
+        ArrayType outerArrayType = parameter.getType().asArrayType();
+
+        ArrayType innerArrayType = outerArrayType.getComponentType().asArrayType();
+        PrimitiveType elementType = innerArrayType.getComponentType().asPrimitiveType();
+
+        assertThat(elementType).isInstanceOf(PrimitiveType.class);
+        assertThat(outerArrayType.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
+        assertThat(innerArrayType.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
+        assertThat(parameter.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
+
+        assertThat(parameter.getType().getParentNode().get()).isSameAs(parameter);
+    }
+
+    @Test
+    void setVariableDeclarationWithArrays() {
+        ExpressionStmt variableDeclarationStatement = parseStatement("@C int @A[] @B[] a @X[] @Y[];").asExpressionStmt();
+        VariableDeclarationExpr variableDeclarationExpr = variableDeclarationStatement.getExpression().asVariableDeclarationExpr();
+
+        variableDeclarationExpr.getVariable(0).setType(new ArrayType(new ArrayType(PrimitiveType.intType())));
+        assertEquals("@C" + EOL + "int[][] a;", variableDeclarationStatement.toString());
+    }
+
+    @Test
+    void setFieldDeclarationWithArrays() {
+        FieldDeclaration fieldDeclaration = parseBodyDeclaration("int[][] a[][];").asFieldDeclaration();
+        fieldDeclaration.getVariable(0).setType(new ArrayType(new ArrayType(parseClassOrInterfaceType("Blob"))));
+
+        assertEquals("Blob[][] a;", fieldDeclaration.toString());
+    }
+
+    @Test
+    void setMethodDeclarationWithArrays() {
+        MethodDeclaration method = parseBodyDeclaration("int[][] a()[][] {}").asMethodDeclaration();
+        method.setType(new ArrayType(new ArrayType(parseClassOrInterfaceType("Blob"))));
+
+        assertEquals("Blob[][] a() {" + EOL + "}", method.toString());
+    }
+
+    @Test
+    void fieldDeclarationWithArraysHasCorrectOrigins() {
+        FieldDeclaration fieldDeclaration = parseBodyDeclaration("int[] a[];").asFieldDeclaration();
+
+        Type outerType = fieldDeclaration.getVariables().get(0).getType();
+        assertEquals(ArrayType.Origin.TYPE, outerType.asArrayType().getOrigin());
+        assertEquals(ArrayType.Origin.NAME, outerType.asArrayType().getComponentType().asArrayType().getOrigin());
+    }
+
+    @Test
+    void methodDeclarationWithArraysHasCorrectOrigins() {
+        MethodDeclaration method = (MethodDeclaration) parseBodyDeclaration("int[] a()[] {}");
+
+        Type outerType = method.getType();
+        assertEquals(ArrayType.Origin.TYPE, outerType.asArrayType().getOrigin());
+        assertEquals(ArrayType.Origin.NAME, outerType.asArrayType().getComponentType().asArrayType().getOrigin());
+    }
+
+    @Test
+    void setParameterWithArrays() {
+        MethodDeclaration method = parseBodyDeclaration("void a(int[][] a[][]) {}").asMethodDeclaration();
+        method.getParameter(0).setType(new ArrayType(new ArrayType(parseClassOrInterfaceType("Blob"))));
+
+        assertEquals("void a(Blob[][] a) {" + EOL + "}", method.toString());
+    }
+
+    @Test
+    void getArrayCreationType() {
+        ArrayCreationExpr expr = parseExpression("new int[]");
+        ArrayType outerType = expr.createdType().asArrayType();
+        Type innerType = outerType.getComponentType();
+        assertThat(innerType).isEqualTo(expr.getElementType());
+    }
+
+    @Test
+    void ellipsisCanHaveAnnotationsToo() {
+        Parameter p = parseParameter("int[]@X...a[]");
+
+        assertThat(p.getVarArgsAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("X")));
+        assertEquals("int[][]@X ... a", p.toString());
+        assertEquals("int[][]@X... a", ConcreteSyntaxModel.genericPrettyPrint(p));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java
new file mode 100644
index 0000000..2804fee
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java
@@ -0,0 +1,69 @@
+package com.github.javaparser.ast.type;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseProblemException;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.validator.Java5Validator;
+import org.junit.jupiter.api.Test;
+
+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 com.github.javaparser.StaticJavaParser.parseType;
+import static com.github.javaparser.StaticJavaParser.parseVariableDeclarationExpr;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class TypeTest {
+    @Test
+    void asString() {
+        assertEquals("int", typeAsString("int x"));
+        assertEquals("List<Long>", typeAsString("List<Long> x"));
+        assertEquals("String", typeAsString("@A String x"));
+        assertEquals("List<? extends Object>", typeAsString("List<? extends Object> x"));
+    }
+
+    @Test
+    void primitiveTypeArgumentDefaultValidator() {
+        assertThrows(ParseProblemException.class, () -> typeAsString("List<long> x;"));
+    }
+
+    @Test
+    void primitiveTypeArgumentLenientValidator() {
+        ParserConfiguration config = new ParserConfiguration()
+                .setLanguageLevel(RAW);
+        config.getPostProcessors().add(new Java5Validator() {{
+            remove(noPrimitiveGenericArguments);
+        }}.postProcessor());
+
+        ParseResult<VariableDeclarationExpr> result = new JavaParser(config).parse(
+                VARIABLE_DECLARATION_EXPR, provider("List<long> x"));
+        assertTrue(result.isSuccessful());
+
+        VariableDeclarationExpr decl = result.getResult().get();
+        assertEquals("List<long>", decl.getVariable(0).getType().asString());
+    }
+
+    private String typeAsString(String s) {
+        return parseVariableDeclarationExpr(s).getVariable(0).getType().asString();
+    }
+
+    @Test
+    void arrayType() {
+        Type type = parseType("int[]");
+        assertTrue(type.isArrayType());
+        ArrayType arrayType = type.asArrayType();
+        final ArrayType[] s = new ArrayType[1];
+        type.ifArrayType(t -> s[0] = t);
+        assertNotNull(s[0]);
+    }
+
+    @Test
+    void issue1251() {
+        final Type type = parseType("TypeUtilsTest<String>.Tester");
+        assertEquals("TypeUtilsTest<String>.Tester", type.toString());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java10ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java10ValidatorTest.java
new file mode 100644
index 0000000..f15750b
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java10ValidatorTest.java
@@ -0,0 +1,114 @@
+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.body.BodyDeclaration;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.CLASS_BODY;
+import static com.github.javaparser.ParseStart.STATEMENT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_10;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java10ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_10));
+
+    @Test
+    void varAllowedInLocalVariableDeclaration() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a = 5;"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void varAllowedInForEach() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(var a : as){}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void varAllowedInOldFor() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(var a = 5;a<9;a++){}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void varNotAllowedInCast() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int a = (var)20;"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void varNotAllowedInTryWithResources() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(var f = new FileReader(\"\")){ }catch (Exception e){ }"));
+        assertProblems(result, "(line 1,col 5) \"var\" is not allowed here.");
+    }
+
+    @Test
+    void varNotAllowedInField() {
+        ParseResult<BodyDeclaration<?>> result = javaParser.parse(CLASS_BODY, provider("var a = 20;"));
+        assertProblems(result, "(line 1,col 1) \"var\" is not allowed here.");
+    }
+
+    @Test
+    void varNotAllowedInTypeArguments() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("new X<var>();"));
+        assertProblems(result, "(line 1,col 7) \"var\" is not allowed here.");
+    }
+
+    @Test
+    void varNotAllowedInLambdaParameters() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("x((var x) -> null);"));
+        assertProblems(result, "(line 1,col 4) \"var\" is not allowed here.");
+    }
+
+    @Test
+    void emptyInitializerNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a;"));
+        assertProblems(result, "(line 1,col 1) \"var\" needs an initializer.");
+    }
+
+    @Test
+    void multipleVariablesNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=1, b=2;"));
+        assertProblems(result, "(line 1,col 1) \"var\" only takes a single variable.");
+    }
+
+    @Test
+    void nullVariablesNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=null;"));
+        assertProblems(result, "(line 1,col 1) \"var\" cannot infer type from just null.");
+    }
+
+    @Test
+    void extraBracketPairsNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var d[] = new int[4];"));
+        assertProblems(result, "(line 1,col 5) \"var\" cannot have extra array brackets.");
+    }
+
+    @Test
+    void arrayDimensionBracketsNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a={ 6 };"));
+        assertProblems(result, "(line 1,col 1) \"var\" cannot infer array types.");
+    }
+
+    // This is pretty hard to impossible to implement correctly with just the AST.
+    @Disabled
+    @Test
+    void selfReferenceNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=a;"));
+        assertProblems(result, "");
+    }
+
+    // Can be implemented once https://github.com/javaparser/javaparser/issues/1434 is implemented.
+    @Disabled
+    @Test
+    void polyExpressionAsInitializerNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=new ArrayList<>();"));
+        assertProblems(result, "");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java11ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java11ValidatorTest.java
new file mode 100644
index 0000000..02b77c4
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java11ValidatorTest.java
@@ -0,0 +1,41 @@
+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.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.STATEMENT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_11;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java11ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_11));
+
+    @Test
+    void varAllowedInLocalVariableDeclaration() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("x((var x, var y) -> x+y);"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void switchExpressionNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int a = switch(x){};"));
+        assertProblems(result, "(line 1,col 9) Switch expressions are not supported.");
+    }
+
+    @Test
+    void multiLabelCaseNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case 3,4,5: ;}"));
+        assertProblems(result, "(line 1,col 11) Only one label allowed in a switch-case.");
+    }
+
+    @Test
+    void noValueBreak() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case 3: break 6;}"));
+        assertProblems(result, "(line 1,col 19) Only labels allowed in break statements.");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java12ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java12ValidatorTest.java
new file mode 100644
index 0000000..e44b524
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java12ValidatorTest.java
@@ -0,0 +1,40 @@
+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.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.STATEMENT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_12;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+
+class Java12ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_12));
+
+    @Test
+    void expressionsInLabelsNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case 3+4+5: ;}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void switchExpressionNotAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int a = switch(x){};"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void multiLabelCaseAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case 3,4,5: ;}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void valueBreakAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case 3: break 6;}"));
+        assertNoProblems(result);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java
new file mode 100644
index 0000000..49656fc
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java
@@ -0,0 +1,116 @@
+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.Problem;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.ArrayCreationExpr;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.PrimitiveType;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.github.javaparser.ParseStart.*;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_1_0;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Java1_0ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_0));
+
+    @Test
+    void tryWithoutResources() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(X x=new Y()){}"));
+        assertProblems(result,
+                "(line 1,col 1) Catch with resource is not supported.",
+                "(line 1,col 1) Try has no finally and no catch.");
+    }
+
+    @Test
+    void classExtendingMoreThanOne() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X extends Y, Z {}"));
+        assertProblems(result, "(line 1,col 20) A class cannot extend more than one other class.");
+    }
+
+    @Test
+    void interfaceUsingImplements() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X implements Y {}"));
+        assertProblems(result, "(line 1,col 24) An interface cannot implement other interfaces.");
+    }
+
+    @Test
+    void interfaceWithInitializer() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X {{}}"));
+        assertProblems(result, "(line 1,col 14) An interface cannot have initializers.");
+    }
+
+    @Test
+    void defaultInClass() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X {default void a(){};}"));
+        assertProblems(result, "(line 1,col 10) 'default' is not allowed here.");
+    }
+
+    @Test
+    void leftHandAssignmentCannotBeAConditional() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("(1==2)=3"));
+        assertProblems(result, "(line 1,col 1) Illegal left hand side of an assignment.");
+    }
+
+    @Test
+    void leftHandAssignmentCannotBeEmptyBraces() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("()=3"));
+        assertProblems(result,
+                "(line 1,col 1) Illegal left hand side of an assignment.",
+                "(line 1,col 1) Lambdas are not supported.");
+    }
+
+    @Test
+    void leftHandAssignmentCanBeInBraces() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("(i) += (i) += 1"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void noInnerClasses() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{class Y{}}"));
+        assertProblems(result, "(line 1,col 9) inner classes or interfaces are not supported.");
+    }
+
+    @Test
+    void noReflection() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("Abc.class"));
+        assertProblems(result, "(line 1,col 1) Reflection is not supported.");
+    }
+
+    @Test
+    void nonEmptyList() {
+        ArrayCreationExpr expr = new ArrayCreationExpr(PrimitiveType.booleanType());
+        List<Problem> problems = new ArrayList<>();
+        new Java1_0Validator().accept(expr, new ProblemReporter(problems::add));
+        assertEquals("ArrayCreationExpr.levels can not be empty.", problems.get(0).getMessage());
+    }
+
+    @Test
+    void noForEach() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(X x : xs){}"));
+        assertProblems(result, "(line 1,col 1) For-each loops are not supported.");
+    }
+
+    @Test
+    void labelBreakAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case 3: break bla;}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void emptyBreakAllowed() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case 3: break;}"));
+        assertNoProblems(result);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_1ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_1ValidatorTest.java
new file mode 100644
index 0000000..89a836e
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_1ValidatorTest.java
@@ -0,0 +1,292 @@
+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.CompilationUnit;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+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.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java1_1ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_1));
+
+    public static final String allModifiers = "public protected private abstract static final transient volatile synchronized native strictfp transitive default ";
+
+    @Test
+    void topClass() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "class X{}"));
+        assertProblems(result,
+                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 1) 'transient' is not allowed here.",
+                "(line 1,col 1) 'default' is not allowed here.",
+                "(line 1,col 1) 'volatile' is not allowed here.",
+                "(line 1,col 1) 'strictfp' is not allowed here.",
+                "(line 1,col 1) 'private' is not allowed here.",
+                "(line 1,col 1) 'protected' is not allowed here.",
+                "(line 1,col 1) 'synchronized' is not allowed here.",
+                "(line 1,col 1) 'native' is not allowed here.",
+                "(line 1,col 1) 'transitive' is not allowed here.",
+                "(line 1,col 1) 'static' is not allowed here."
+        );
+    }
+
+    @Test
+    void nestedClass() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "class I{}}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void localClass() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{ void x() {" + allModifiers + "class I{}}}"));
+        assertProblems(result,
+                "(line 1,col 20) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 20) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 20) 'transient' is not allowed here.",
+                "(line 1,col 20) 'volatile' is not allowed here.",
+                "(line 1,col 20) 'default' is not allowed here.",
+                "(line 1,col 20) 'synchronized' is not allowed here.",
+                "(line 1,col 20) 'native' is not allowed here.",
+                "(line 1,col 20) 'transitive' is not allowed here.",
+                "(line 1,col 20) 'strictfp' is not allowed here.",
+                "(line 1,col 20) 'static' is not allowed here.",
+                "(line 1,col 20) 'public' is not allowed here.",
+                "(line 1,col 20) 'private' is not allowed here.",
+                "(line 1,col 20) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void topInterface() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "interface X{}"));
+        assertProblems(result,
+                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 1) 'transient' is not allowed here.",
+                "(line 1,col 1) 'volatile' is not allowed here.",
+                "(line 1,col 1) 'default' is not allowed here.",
+                "(line 1,col 1) 'strictfp' is not allowed here.",
+                "(line 1,col 1) 'synchronized' is not allowed here.",
+                "(line 1,col 1) 'native' is not allowed here.",
+                "(line 1,col 1) 'transitive' is not allowed here.",
+                "(line 1,col 1) 'static' is not allowed here.",
+                "(line 1,col 1) 'final' is not allowed here.",
+                "(line 1,col 1) 'private' is not allowed here.",
+                "(line 1,col 1) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void nestedInterface() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "interface I{}}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'final' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void constructor() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "X(){};}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'final' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'abstract' is not allowed here.",
+                "(line 1,col 9) 'static' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void constructorParameter() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{X(" + allModifiers + " int i){};}"));
+        assertProblems(result,
+                "(line 1,col 11) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 11) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 11) 'transient' is not allowed here.",
+                "(line 1,col 11) 'volatile' is not allowed here.",
+                "(line 1,col 11) 'synchronized' is not allowed here.",
+                "(line 1,col 11) 'native' is not allowed here.",
+                "(line 1,col 11) 'strictfp' is not allowed here.",
+                "(line 1,col 11) 'default' is not allowed here.",
+                "(line 1,col 11) 'abstract' is not allowed here.",
+                "(line 1,col 11) 'static' is not allowed here.",
+                "(line 1,col 11) 'transitive' is not allowed here.",
+                "(line 1,col 11) 'private' is not allowed here.",
+                "(line 1,col 11) 'public' is not allowed here.",
+                "(line 1,col 11) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void classMethod() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int x(){};}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void interfaceMethod() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
+        assertProblems(result,
+                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
+                "(line 1,col 13) 'transient' is not allowed here.",
+                "(line 1,col 13) 'strictfp' is not allowed here.",
+                "(line 1,col 13) 'volatile' is not allowed here.",
+                "(line 1,col 13) 'default' is not allowed here.",
+                "(line 1,col 13) 'transitive' is not allowed here.",
+                "(line 1,col 13) 'private' is not allowed here.",
+                "(line 1,col 13) 'static' is not allowed here."
+        );
+    }
+
+    @Test
+    void methodParameter() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(" + allModifiers + " int i){};}"));
+        assertProblems(result,
+                "(line 1,col 15) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 15) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 15) 'transient' is not allowed here.",
+                "(line 1,col 15) 'volatile' is not allowed here.",
+                "(line 1,col 15) 'synchronized' is not allowed here.",
+                "(line 1,col 15) 'native' is not allowed here.",
+                "(line 1,col 15) 'strictfp' is not allowed here.",
+                "(line 1,col 15) 'abstract' is not allowed here.",
+                "(line 1,col 15) 'default' is not allowed here.",
+                "(line 1,col 15) 'static' is not allowed here.",
+                "(line 1,col 15) 'transitive' is not allowed here.",
+                "(line 1,col 15) 'private' is not allowed here.",
+                "(line 1,col 15) 'public' is not allowed here.",
+                "(line 1,col 15) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void field() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int i;}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'abstract' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void localVariable() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){" + allModifiers + "int i;}}"));
+        assertProblems(result,
+                "(line 1,col 17) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 17) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 17) 'transient' is not allowed here.",
+                "(line 1,col 17) 'volatile' is not allowed here.",
+                "(line 1,col 17) 'synchronized' is not allowed here.",
+                "(line 1,col 17) 'native' is not allowed here.",
+                "(line 1,col 17) 'default' is not allowed here.",
+                "(line 1,col 17) 'strictfp' is not allowed here.",
+                "(line 1,col 17) 'abstract' is not allowed here.",
+                "(line 1,col 17) 'static' is not allowed here.",
+                "(line 1,col 17) 'transitive' is not allowed here.",
+                "(line 1,col 17) 'private' is not allowed here.",
+                "(line 1,col 17) 'public' is not allowed here.",
+                "(line 1,col 17) 'protected' is not allowed here."
+        );
+    }
+
+
+    @Test
+    void catchParameter() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){ try{}catch(" + allModifiers + " Integer x){}}}"));
+        assertProblems(result,
+                "(line 1,col 29) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 29) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 29) 'transient' is not allowed here.",
+                "(line 1,col 29) 'volatile' is not allowed here.",
+                "(line 1,col 29) 'synchronized' is not allowed here.",
+                "(line 1,col 29) 'native' is not allowed here.",
+                "(line 1,col 29) 'default' is not allowed here.",
+                "(line 1,col 29) 'strictfp' is not allowed here.",
+                "(line 1,col 29) 'abstract' is not allowed here.",
+                "(line 1,col 29) 'static' is not allowed here.",
+                "(line 1,col 29) 'transitive' is not allowed here.",
+                "(line 1,col 29) 'private' is not allowed here.",
+                "(line 1,col 29) 'public' is not allowed here.",
+                "(line 1,col 29) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void innerClasses() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{class Y{}}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void localInterface() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{ void x() {" + allModifiers + "interface I{}}}"));
+        assertProblems(result, "(line 1,col 20) There is no such thing as a local interface."
+        );
+    }
+
+    @Test
+    void reflection() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("Abc.class"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void strictfpAllowedAsIdentifier() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int strictfp;"));
+        assertNoProblems(result);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_2ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_2ValidatorTest.java
new file mode 100644
index 0000000..fef970d
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_2ValidatorTest.java
@@ -0,0 +1,274 @@
+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.CompilationUnit;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+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.assertProblems;
+
+class Java1_2ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_2));
+
+    private final String allModifiers = "public protected private abstract static final transient volatile synchronized native strictfp transitive default ";
+
+    @Test
+    void topClass() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "class X{}"));
+        assertProblems(result,
+                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 1) 'transient' is not allowed here.",
+                "(line 1,col 1) 'default' is not allowed here.",
+                "(line 1,col 1) 'volatile' is not allowed here.",
+                "(line 1,col 1) 'private' is not allowed here.",
+                "(line 1,col 1) 'protected' is not allowed here.",
+                "(line 1,col 1) 'synchronized' is not allowed here.",
+                "(line 1,col 1) 'native' is not allowed here.",
+                "(line 1,col 1) 'transitive' is not allowed here.",
+                "(line 1,col 1) 'static' is not allowed here."
+        );
+    }
+
+    @Test
+    void nestedClass() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "class I{}}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void localClass() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{ void x() {" + allModifiers + "class I{}}}"));
+        assertProblems(result,
+                "(line 1,col 20) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 20) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 20) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 20) 'transient' is not allowed here.",
+                "(line 1,col 20) 'volatile' is not allowed here.",
+                "(line 1,col 20) 'default' is not allowed here.",
+                "(line 1,col 20) 'synchronized' is not allowed here.",
+                "(line 1,col 20) 'native' is not allowed here.",
+                "(line 1,col 20) 'transitive' is not allowed here.",
+                "(line 1,col 20) 'static' is not allowed here.",
+                "(line 1,col 20) 'public' is not allowed here.",
+                "(line 1,col 20) 'private' is not allowed here.",
+                "(line 1,col 20) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void topInterface() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "interface X{}"));
+        assertProblems(result,
+                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 1) 'transient' is not allowed here.",
+                "(line 1,col 1) 'volatile' is not allowed here.",
+                "(line 1,col 1) 'default' is not allowed here.",
+                "(line 1,col 1) 'synchronized' is not allowed here.",
+                "(line 1,col 1) 'native' is not allowed here.",
+                "(line 1,col 1) 'transitive' is not allowed here.",
+                "(line 1,col 1) 'static' is not allowed here.",
+                "(line 1,col 1) 'final' is not allowed here.",
+                "(line 1,col 1) 'private' is not allowed here.",
+                "(line 1,col 1) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void nestedInterface() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "interface I{}}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'final' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void constructor() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "X(){};}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'final' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'abstract' is not allowed here.",
+                "(line 1,col 9) 'static' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void constructorParameter() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{X(" + allModifiers + " int i){};}"));
+        assertProblems(result,
+                "(line 1,col 11) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 11) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 11) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 11) 'transient' is not allowed here.",
+                "(line 1,col 11) 'volatile' is not allowed here.",
+                "(line 1,col 11) 'synchronized' is not allowed here.",
+                "(line 1,col 11) 'native' is not allowed here.",
+                "(line 1,col 11) 'strictfp' is not allowed here.",
+                "(line 1,col 11) 'default' is not allowed here.",
+                "(line 1,col 11) 'abstract' is not allowed here.",
+                "(line 1,col 11) 'static' is not allowed here.",
+                "(line 1,col 11) 'transitive' is not allowed here.",
+                "(line 1,col 11) 'private' is not allowed here.",
+                "(line 1,col 11) 'public' is not allowed here.",
+                "(line 1,col 11) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void classMethod() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int x(){};}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 9) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void interfaceMethod() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
+        assertProblems(result,
+                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 13) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
+                "(line 1,col 13) 'transient' is not allowed here.",
+                "(line 1,col 13) 'volatile' is not allowed here.",
+                "(line 1,col 13) 'default' is not allowed here.",
+                "(line 1,col 13) 'transitive' is not allowed here.",
+                "(line 1,col 13) 'private' is not allowed here.",
+                "(line 1,col 13) 'static' is not allowed here."
+        );
+    }
+
+    @Test
+    void methodParameter() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(" + allModifiers + " int i){};}"));
+        assertProblems(result,
+                "(line 1,col 15) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 15) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 15) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 15) 'transient' is not allowed here.",
+                "(line 1,col 15) 'volatile' is not allowed here.",
+                "(line 1,col 15) 'synchronized' is not allowed here.",
+                "(line 1,col 15) 'native' is not allowed here.",
+                "(line 1,col 15) 'strictfp' is not allowed here.",
+                "(line 1,col 15) 'abstract' is not allowed here.",
+                "(line 1,col 15) 'default' is not allowed here.",
+                "(line 1,col 15) 'static' is not allowed here.",
+                "(line 1,col 15) 'transitive' is not allowed here.",
+                "(line 1,col 15) 'private' is not allowed here.",
+                "(line 1,col 15) 'public' is not allowed here.",
+                "(line 1,col 15) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void field() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int i;}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'strictfp' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'abstract' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void localVariable() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){" + allModifiers + "int i;}}"));
+        assertProblems(result,
+                "(line 1,col 17) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 17) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 17) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 17) 'transient' is not allowed here.",
+                "(line 1,col 17) 'volatile' is not allowed here.",
+                "(line 1,col 17) 'synchronized' is not allowed here.",
+                "(line 1,col 17) 'native' is not allowed here.",
+                "(line 1,col 17) 'default' is not allowed here.",
+                "(line 1,col 17) 'strictfp' is not allowed here.",
+                "(line 1,col 17) 'abstract' is not allowed here.",
+                "(line 1,col 17) 'static' is not allowed here.",
+                "(line 1,col 17) 'transitive' is not allowed here.",
+                "(line 1,col 17) 'private' is not allowed here.",
+                "(line 1,col 17) 'public' is not allowed here.",
+                "(line 1,col 17) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void catchParameter() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){ try{}catch(" + allModifiers + " Integer x){}}}"));
+        assertProblems(result,
+                "(line 1,col 29) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 29) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 29) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 29) 'transient' is not allowed here.",
+                "(line 1,col 29) 'volatile' is not allowed here.",
+                "(line 1,col 29) 'synchronized' is not allowed here.",
+                "(line 1,col 29) 'native' is not allowed here.",
+                "(line 1,col 29) 'default' is not allowed here.",
+                "(line 1,col 29) 'strictfp' is not allowed here.",
+                "(line 1,col 29) 'abstract' is not allowed here.",
+                "(line 1,col 29) 'static' is not allowed here.",
+                "(line 1,col 29) 'transitive' is not allowed here.",
+                "(line 1,col 29) 'private' is not allowed here.",
+                "(line 1,col 29) 'public' is not allowed here.",
+                "(line 1,col 29) 'protected' is not allowed here."
+        );
+    }
+    
+    @Test
+    void strictfpNotAllowedAsIdentifier() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int strictfp;"));
+        assertProblems(result, "(line 1,col 5) 'strictfp' cannot be used as an identifier as it is a keyword.");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_3ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_3ValidatorTest.java
new file mode 100644
index 0000000..875ef0e
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_3ValidatorTest.java
@@ -0,0 +1,22 @@
+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.jupiter.api.Test;
+
+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.assertProblems;
+
+class Java1_3ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_3));
+
+    @Test
+    void noAssert() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("assert a;"));
+        assertProblems(result, "(line 1,col 1) 'assert' keyword is not supported.");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_4ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_4ValidatorTest.java
new file mode 100644
index 0000000..f0e08b6
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java1_4ValidatorTest.java
@@ -0,0 +1,70 @@
+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.CompilationUnit;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.*;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java1_4ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_4));
+
+    @Test
+    void yesAssert() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("assert a;"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void noGenerics() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X<A>{List<String> b;}"));
+        assertProblems(result,
+                "(line 1,col 12) Generics are not supported.",
+                "(line 1,col 1) Generics are not supported."
+        );
+    }
+
+    @Test
+    void noAnnotations() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("@Abc @Def() @Ghi(a=3) @interface X{}"));
+        assertProblems(result,
+                "(line 1,col 6) Annotations are not supported.",
+                "(line 1,col 13) Annotations are not supported.",
+                "(line 1,col 1) Annotations are not supported."
+        );
+    }
+
+    @Test
+    void novarargs() {
+        ParseResult<Parameter> result = javaParser.parse(PARAMETER, provider("String... x"));
+        assertProblems(result, "(line 1,col 1) Varargs are not supported.");
+    }
+
+    @Test
+    void noforeach() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(X x: xs){}"));
+        assertProblems(result, "(line 1,col 1) For-each loops are not supported.");
+    }
+
+    @Test
+    void staticImport() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("import static x;import static x.*;import x.X;import x.*;"));
+        assertProblems(result,
+                "(line 1,col 17) Static imports are not supported.",
+                "(line 1,col 1) Static imports are not supported.");
+    }
+
+    @Test
+    void enumAllowedAsIdentifier() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int enum;"));
+        assertNoProblems(result);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java5ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java5ValidatorTest.java
new file mode 100644
index 0000000..10578ae
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java5ValidatorTest.java
@@ -0,0 +1,173 @@
+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.CompilationUnit;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.*;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_5;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.ast.validator.Java1_1ValidatorTest.allModifiers;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java5ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_5));
+
+    @Test
+    void genericsWithoutDiamond() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X<A>{List<String> b = new ArrayList<>();}"));
+        assertProblems(result, "(line 1,col 33) The diamond operator is not supported.");
+    }
+
+    @Test
+    void topAnnotationDeclaration() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "@interface X{}"));
+        assertProblems(result,
+                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 1) 'transient' is not allowed here.",
+                "(line 1,col 1) 'volatile' is not allowed here.",
+                "(line 1,col 1) 'synchronized' is not allowed here.",
+                "(line 1,col 1) 'default' is not allowed here.",
+                "(line 1,col 1) 'native' is not allowed here.",
+                "(line 1,col 1) 'transitive' is not allowed here.",
+                "(line 1,col 1) 'static' is not allowed here.",
+                "(line 1,col 1) 'final' is not allowed here.",
+                "(line 1,col 1) 'private' is not allowed here.",
+                "(line 1,col 1) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void nestedAnnotationDeclaration() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "@interface I{}}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'final' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void annotationMember() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("@interface X{" + allModifiers + "int x();}"));
+        assertProblems(result,
+                "(line 1,col 14) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 14) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 14) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 14) 'transient' is not allowed here.",
+                "(line 1,col 14) 'volatile' is not allowed here.",
+                "(line 1,col 14) 'final' is not allowed here.",
+                "(line 1,col 14) 'synchronized' is not allowed here.",
+                "(line 1,col 14) 'default' is not allowed here.",
+                "(line 1,col 14) 'native' is not allowed here.",
+                "(line 1,col 14) 'protected' is not allowed here.",
+                "(line 1,col 14) 'private' is not allowed here.",
+                "(line 1,col 14) 'strictfp' is not allowed here.",
+                "(line 1,col 14) 'static' is not allowed here.",
+                "(line 1,col 14) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void topEnum() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "enum X{}"));
+        assertProblems(result,
+                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 1) 'transient' is not allowed here.",
+                "(line 1,col 1) 'volatile' is not allowed here.",
+                "(line 1,col 1) 'synchronized' is not allowed here.",
+                "(line 1,col 1) 'default' is not allowed here.",
+                "(line 1,col 1) 'native' is not allowed here.",
+                "(line 1,col 1) 'transitive' is not allowed here.",
+                "(line 1,col 1) 'static' is not allowed here.",
+                "(line 1,col 1) 'abstract' is not allowed here.",
+                "(line 1,col 1) 'final' is not allowed here.",
+                "(line 1,col 1) 'private' is not allowed here.",
+                "(line 1,col 1) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void nestedEnum() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "enum I{}}"));
+        assertProblems(result,
+                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 9) 'transient' is not allowed here.",
+                "(line 1,col 9) 'volatile' is not allowed here.",
+                "(line 1,col 9) 'default' is not allowed here.",
+                "(line 1,col 9) 'abstract' is not allowed here.",
+                "(line 1,col 9) 'final' is not allowed here.",
+                "(line 1,col 9) 'synchronized' is not allowed here.",
+                "(line 1,col 9) 'native' is not allowed here.",
+                "(line 1,col 9) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void varargs() {
+        ParseResult<Parameter> result = javaParser.parse(PARAMETER, provider("String... x"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void foreach() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(X x: xs){}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void noMultipleVariablesInForEach() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(int i, j : nums){}"));
+        assertProblems(result,
+                "(line 1,col 1) A foreach statement's variable declaration must have exactly one variable declarator. Given: 2.");
+    }
+
+    @Test
+    void noModifiersInForEachBesideFinal() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(static transient int i : nums){}"));
+        assertProblems(result,
+                "(line 1,col 5) 'static' is not allowed here.", "(line 1,col 5) 'transient' is not allowed here.");
+    }
+
+    @Test
+    void staticImport() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("import static x;import static x.*;import x.X;import x.*;"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void noPrimitiveTypeArguments() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X extends Y<int> {}"));
+        assertProblems(result, "(line 1,col 17) Type arguments may not be primitive.");
+    }
+
+    @Test
+    void enumAllowedAsIdentifier() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int enum;"));
+        assertProblems(result, "(line 1,col 5) 'enum' cannot be used as an identifier as it is a keyword.");
+    }
+
+    @Test
+    void enumAllowedInSwitch() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case GREEN: ;}"));
+        assertNoProblems(result);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java6ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java6ValidatorTest.java
new file mode 100644
index 0000000..61e2f2d
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java6ValidatorTest.java
@@ -0,0 +1,36 @@
+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.expr.Expression;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+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.assertProblems;
+
+class Java6ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_6));
+
+    @Test
+    void nobinaryIntegerLiterals() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("0b01"));
+        assertProblems(result, "(line 1,col 1) Binary literal values are not supported.");
+    }
+
+    @Test
+    void noUnderscoresInIntegerLiterals() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("1_000_000"));
+        assertProblems(result, "(line 1,col 1) Underscores in literal values are not supported.");
+    }
+
+    @Test
+    void noMultiCatch() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try{}catch(Abc|Def e){}"));
+        assertProblems(result, "(line 1,col 12) Multi-catch is not supported.");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java
new file mode 100644
index 0000000..748f4c2
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java
@@ -0,0 +1,107 @@
+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.Problem;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.type.UnionType;
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+
+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.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java7ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_7));
+
+    @Test
+    void generics() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X<A>{List<String> b = new ArrayList<>();}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void defaultMethodWithoutBody() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X {default void a();}"));
+        assertProblems(result, "(line 1,col 14) 'default' is not allowed here.");
+    }
+
+    @Test
+    void tryWithoutAnything() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try{}"));
+        assertProblems(result, "(line 1,col 1) Try has no finally, no catch, and no resources.");
+    }
+
+    @Test
+    void tryWithResourceVariableDeclaration() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(Reader r = new Reader()){}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void tryWithResourceReference() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(a.b.c){}"));
+        assertProblems(result, "(line 1,col 1) Try with resources only supports variable declarations.");
+    }
+
+    @Test
+    void stringsInSwitch() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case \"abc\": ;}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void binaryIntegerLiterals() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("0b01"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void underscoresInIntegerLiterals() {
+        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("1_000_000"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void multiCatch() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try{}catch(Abc|Def e){}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void multiCatchWithoutElements() {
+        UnionType unionType = new UnionType();
+
+        List<Problem> problems = new ArrayList<>();
+        new Java7Validator().accept(unionType, new ProblemReporter(problems::add));
+        
+        assertProblems(problems, "UnionType.elements can not be empty.");
+    }
+
+    @Test
+    void multiCatchWithOneElement() {
+        UnionType unionType = new UnionType();
+        unionType.getElements().add(new ClassOrInterfaceType());
+
+        List<Problem> problems = new ArrayList<>();
+        new Java7Validator().accept(unionType, new ProblemReporter(problems::add));
+        
+        assertProblems(problems, "Union type (multi catch) must have at least two elements.");
+    }
+
+    @Test
+    void noLambdas() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("a(() -> 1);"));
+        assertProblems(result, "(line 1,col 3) Lambdas are not supported.");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java8ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java8ValidatorTest.java
new file mode 100644
index 0000000..a1e03fc
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java8ValidatorTest.java
@@ -0,0 +1,82 @@
+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.CompilationUnit;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+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.ast.validator.Java1_1ValidatorTest.allModifiers;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java8ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_8));
+
+    @Test
+    void localInterface() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X {void a(){interface I{}};}"));
+        assertProblems(result, "(line 1,col 19) There is no such thing as a local interface.");
+    }
+
+    @Test
+    void lambdaParameter() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){ a((" + allModifiers + " Integer x) -> 10);}}"));
+        assertProblems(result,
+                "(line 1,col 21) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 21) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 21) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 21) 'transient' is not allowed here.",
+                "(line 1,col 21) 'volatile' is not allowed here.",
+                "(line 1,col 21) 'synchronized' is not allowed here.",
+                "(line 1,col 21) 'strictfp' is not allowed here.",
+                "(line 1,col 21) 'default' is not allowed here.",
+                "(line 1,col 21) 'native' is not allowed here.",
+                "(line 1,col 21) 'strictfp' is not allowed here.",
+                "(line 1,col 21) 'abstract' is not allowed here.",
+                "(line 1,col 21) 'static' is not allowed here.",
+                "(line 1,col 21) 'transitive' is not allowed here.",
+                "(line 1,col 21) 'private' is not allowed here.",
+                "(line 1,col 21) 'public' is not allowed here.",
+                "(line 1,col 21) 'protected' is not allowed here."
+        );
+    }
+
+    @Test
+    void interfaceMethod() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
+        assertProblems(result,
+                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 13) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
+                "(line 1,col 13) 'transient' is not allowed here.",
+                "(line 1,col 13) 'volatile' is not allowed here.",
+                "(line 1,col 13) 'transitive' is not allowed here.",
+                "(line 1,col 13) 'private' is not allowed here."
+        );
+    }
+
+    @Test
+    void defaultMethodWithoutBody() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X {default void a();}"));
+        assertProblems(result, "(line 1,col 14) 'default' methods must have a body.");
+    }
+
+    @Test
+    void lambdas() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("a(() -> 1);"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void noModules() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("open module x {}"));
+        assertProblems(result, "(line 1,col 1) Modules are not supported.");
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java9ValidatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java9ValidatorTest.java
new file mode 100644
index 0000000..59af03d
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/validator/Java9ValidatorTest.java
@@ -0,0 +1,79 @@
+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.CompilationUnit;
+import com.github.javaparser.ast.stmt.Statement;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+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.ast.validator.Java1_1ValidatorTest.allModifiers;
+import static com.github.javaparser.utils.TestUtils.assertNoProblems;
+import static com.github.javaparser.utils.TestUtils.assertProblems;
+
+class Java9ValidatorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
+
+    @Test
+    void underscoreIdentifiers() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("a.b._.c.d = act(_, _ -> _);"));
+        assertProblems(result,
+                "(line 1,col 5) '_' is a reserved keyword.",
+                "(line 1,col 17) '_' is a reserved keyword.",
+                "(line 1,col 20) '_' is a reserved keyword.",
+                "(line 1,col 25) '_' is a reserved keyword."
+        );
+    }
+
+    @Test
+    void moduleRequires() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("module x{requires " + allModifiers + " a;}"));
+        assertProblems(result,
+                "(line 1,col 10) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 10) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 10) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 10) 'transient' is not allowed here.",
+                "(line 1,col 10) 'volatile' is not allowed here.",
+                "(line 1,col 10) 'final' is not allowed here.",
+                "(line 1,col 10) 'synchronized' is not allowed here.",
+                "(line 1,col 10) 'default' is not allowed here.",
+                "(line 1,col 10) 'native' is not allowed here.",
+                "(line 1,col 10) 'private' is not allowed here.",
+                "(line 1,col 10) 'protected' is not allowed here.",
+                "(line 1,col 10) 'strictfp' is not allowed here.",
+                "(line 1,col 10) 'abstract' is not allowed here.",
+                "(line 1,col 10) 'public' is not allowed here."
+        );
+    }
+
+    @Test
+    void interfaceMethod() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
+        assertProblems(result,
+                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
+                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
+                "(line 1,col 13) Can have only one of 'native', 'strictfp'.",
+                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
+                "(line 1,col 13) 'transient' is not allowed here.",
+                "(line 1,col 13) 'volatile' is not allowed here.",
+                "(line 1,col 13) 'transitive' is not allowed here."
+        );
+    }
+
+    @Test
+    void modules() {
+        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("open module x {}"));
+        assertNoProblems(result);
+    }
+
+    @Test
+    void tryWithResourceReference() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(a.b.c){}"));
+        assertNoProblems(result);
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/CloneVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/CloneVisitorTest.java
new file mode 100644
index 0000000..e2e2a33
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/CloneVisitorTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.visitor;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.type.Type;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Iterator;
+
+import static com.github.javaparser.StaticJavaParser.parseType;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CloneVisitorTest {
+    CompilationUnit cu;
+
+    @BeforeEach
+    void setUp() {
+        cu = new CompilationUnit();
+    }
+
+    @AfterEach
+    void teardown() {
+        cu = null;
+    }
+
+    @Test
+    void cloneJavaDocTest() {
+        NodeList<BodyDeclaration<?>> bodyDeclarationList = new NodeList<>();
+        bodyDeclarationList.add(new AnnotationMemberDeclaration().setJavadocComment("javadoc"));
+        bodyDeclarationList.add(new ConstructorDeclaration().setJavadocComment("javadoc"));
+        bodyDeclarationList.add(new EnumConstantDeclaration().setJavadocComment("javadoc"));
+        bodyDeclarationList.add(new FieldDeclaration().setJavadocComment("javadoc"));
+        bodyDeclarationList.add(new InitializerDeclaration().setJavadocComment("javadoc"));
+        bodyDeclarationList.add(new MethodDeclaration().setJavadocComment("javadoc"));
+
+        NodeList<TypeDeclaration<?>> typeDeclarationList = new NodeList<>();
+        AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration();
+        annotationDeclaration.setName("nnotationDeclarationTest");
+        typeDeclarationList.add(annotationDeclaration.setJavadocComment("javadoc"));
+
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration2 = new ClassOrInterfaceDeclaration();
+        classOrInterfaceDeclaration2.setName("emptyTypeDeclarationTest");
+        typeDeclarationList.add(classOrInterfaceDeclaration2.setJavadocComment("javadoc"));
+
+        EnumDeclaration enumDeclaration = new EnumDeclaration();
+        enumDeclaration.setName("enumDeclarationTest");
+        typeDeclarationList.add(enumDeclaration.setJavadocComment("javadoc"));
+
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration();
+        classOrInterfaceDeclaration.setName("classOrInterfaceDeclarationTest");
+        typeDeclarationList.add(classOrInterfaceDeclaration.setJavadocComment("javadoc"));
+
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration1 = new ClassOrInterfaceDeclaration();
+        classOrInterfaceDeclaration1.setName("emptyTypeDeclarationTest1");
+        typeDeclarationList.add(classOrInterfaceDeclaration2.setMembers(bodyDeclarationList));
+
+        cu.setTypes(typeDeclarationList);
+        CompilationUnit cuClone = (CompilationUnit) new CloneVisitor().visit(cu, null);
+
+        NodeList<TypeDeclaration<?>> typeDeclarationListClone = cuClone.getTypes();
+        Iterator<TypeDeclaration<?>> typeItr = typeDeclarationListClone.iterator();
+        TypeDeclaration<?> typeDeclaration;
+        while (typeItr.hasNext()) {
+            typeDeclaration = typeItr.next();
+            if (typeDeclaration.getMembers() == null) {
+                assertEquals("javadoc", typeDeclaration.getComment().get().getContent());
+            } else {
+                Iterator<BodyDeclaration<?>> bodyItr = typeDeclaration.getMembers().iterator();
+                while (bodyItr.hasNext()) {
+                    BodyDeclaration<?> bodyDeclaration = bodyItr.next();
+                    assertEquals("javadoc", bodyDeclaration.getComment().get().getContent());
+                }
+            }
+        }
+    }
+    
+    @Test
+    void cloneAnnotationOnWildcardTypeArgument() {
+        Type type = parseType("List<@C ? extends Object>").clone();
+        assertEquals("List<@C ? extends Object>", type.toString());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/HashCodeVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/HashCodeVisitorTest.java
new file mode 100644
index 0000000..39854f9
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/HashCodeVisitorTest.java
@@ -0,0 +1,24 @@
+package com.github.javaparser.ast.visitor;
+
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+class HashCodeVisitorTest {
+    @Test
+    void testEquals() {
+        CompilationUnit p1 = parse("class X { }");
+        CompilationUnit p2 = parse("class X { }");
+        assertEquals(p1.hashCode(), p2.hashCode());
+    }
+
+    @Test
+    void testNotEquals() {
+        CompilationUnit p1 = parse("class X { }");
+        CompilationUnit p2 = parse("class Y { }");
+        assertNotEquals(p1.hashCode(), p2.hashCode());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/ModifierVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/ModifierVisitorTest.java
new file mode 100644
index 0000000..f9b6cc3
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/ModifierVisitorTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.visitor;
+
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.StringLiteralExpr;
+import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseBodyDeclaration;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+class ModifierVisitorTest {
+    @Test
+    void makeSureParentListsCanBeModified() {
+        NodeList<StringLiteralExpr> list = new NodeList<>();
+        list.add(new StringLiteralExpr("t"));
+        list.add(new StringLiteralExpr("a"));
+        list.add(new StringLiteralExpr("b"));
+        list.add(new StringLiteralExpr("c"));
+
+        list.accept(new ModifierVisitor<Void>() {
+            @Override
+            public Visitable visit(final StringLiteralExpr n, final Void arg) {
+                String v = n.getValue();
+
+                list.addFirst(new StringLiteralExpr("extra " + v));
+                list.remove(new StringLiteralExpr("t"));
+
+                if (v.equals("a")) {
+                    return new StringLiteralExpr("x");
+                }
+                if (v.equals("b")) {
+                    return null;
+                }
+
+                return n;
+            }
+        }, null);
+
+        assertEquals("extra c", list.get(0).getValue());
+        assertEquals("extra b", list.get(1).getValue());
+        assertEquals("extra a", list.get(2).getValue());
+        assertEquals("extra t", list.get(3).getValue());
+        assertEquals("x", list.get(4).getValue());
+        assertEquals("c", list.get(5).getValue());
+        assertEquals(6, list.size());
+    }
+
+    @Test
+    void binaryExprReturnsLeftExpressionWhenRightSideIsRemoved() {
+        Expression expression = parseExpression("1+2");
+        Visitable result = expression.accept(new ModifierVisitor<Void>() {
+            public Visitable visit(IntegerLiteralExpr integerLiteralExpr, Void arg) {
+                if (integerLiteralExpr.getValue().equals("1")) {
+                    return null;
+                }
+                return integerLiteralExpr;
+            }
+        }, null);
+        assertEquals("2", result.toString());
+    }
+
+    @Test
+    void binaryExprReturnsRightExpressionWhenLeftSideIsRemoved() {
+        final Expression expression = parseExpression("1+2");
+        final Visitable result = expression.accept(new ModifierVisitor<Void>() {
+            public Visitable visit(IntegerLiteralExpr integerLiteralExpr, Void arg) {
+                if (integerLiteralExpr.getValue().equals("2")) {
+                    return null;
+                }
+                return integerLiteralExpr;
+            }
+        }, null);
+        assertEquals("1", result.toString());
+    }
+
+    @Test
+    void fieldDeclarationCantSurviveWithoutVariables() {
+        final BodyDeclaration<?> bodyDeclaration = parseBodyDeclaration("int x=1;");
+
+        final Visitable result = bodyDeclaration.accept(new ModifierVisitor<Void>() {
+            public Visitable visit(VariableDeclarator x, Void arg) {
+                return null;
+            }
+        }, null);
+
+        assertNull(result);
+    }
+
+    @Test
+    void variableDeclarationCantSurviveWithoutVariables() {
+        final BodyDeclaration<?> bodyDeclaration = parseBodyDeclaration("void x() {int x=1;}");
+
+        final Visitable result = bodyDeclaration.accept(new ModifierVisitor<Void>() {
+            public Visitable visit(VariableDeclarator x, Void arg) {
+                return null;
+            }
+        }, null);
+
+        assertEquals("void x() {" + EOL + "}", result.toString());
+    }
+
+    @Test
+    void issue2124() {
+        ModifierVisitor<Void> modifier = new ModifierVisitor<>();
+        CompilationUnit cu = StaticJavaParser.parse("\n" +
+                "public class ModifierVisitorTest {\n" +
+                "    private void causesException() {\n" +
+                "        String[] listWithExtraCommaAndEqualElements = {\"a\", \"a\",};\n" +
+                "    }\n" +
+                "}");
+        LexicalPreservingPrinter.setup(cu);
+        cu.accept(modifier, null);
+        System.out.println(LexicalPreservingPrinter.print(cu));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitorTest.java
new file mode 100644
index 0000000..b91715d
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitorTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.
+ *
+ * This file is part of 
+ *
+ * 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.visitor;
+
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NoCommentEqualsVisitorTest {
+
+    @Test
+    void testEquals() {
+        CompilationUnit p1 = parse("class X { }");
+        CompilationUnit p2 = parse("class X { }");
+        assertTrue(NoCommentEqualsVisitor.equals(p1, p2));
+    }
+
+    @Test
+    void testEqualsWithDifferentComments() {
+        CompilationUnit p1 = parse("/* a */ class X { /** b */} //c");
+        CompilationUnit p2 = parse("/* b */ class X { }  //c");
+        assertTrue(NoCommentEqualsVisitor.equals(p1, p2));
+    }
+
+    @Test
+    void testNotEquals() {
+        CompilationUnit p1 = parse("class X { }");
+        CompilationUnit p2 = parse("class Y { }");
+        assertFalse(NoCommentEqualsVisitor.equals(p1, p2));
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitorTest.java
new file mode 100644
index 0000000..ae56a13
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitorTest.java
@@ -0,0 +1,34 @@
+package com.github.javaparser.ast.visitor;
+
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+class NoCommentHashCodeVisitorTest {
+
+    @Test
+    void testEquals() {
+        CompilationUnit p1 = parse("class X { }");
+        CompilationUnit p2 = parse("class X { }");
+        assertEquals(p1.hashCode(), p2.hashCode());
+    }
+
+    @Test
+    void testEqualsWithDifferentComments() {
+        CompilationUnit p1 = parse("/* a */ class X { /** b */} //c");
+        CompilationUnit p2 = parse("/* b */ class X { }  //c");
+        assertEquals(p1.hashCode(), p2.hashCode());
+        assertEquals(p1.getComments().size(), 3);
+        assertEquals(p2.getComments().size(), 2);
+    }
+
+    @Test
+    void testNotEquals() {
+        CompilationUnit p1 = parse("class X { }");
+        CompilationUnit p2 = parse("class Y { }");
+        assertNotEquals(p1.hashCode(), p2.hashCode());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/TreeVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/TreeVisitorTest.java
new file mode 100644
index 0000000..aa39476
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/ast/visitor/TreeVisitorTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.visitor;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.ArrayInitializerExpr;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.SimpleName;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+class TreeVisitorTest {
+    @Test
+    void isValidBreadthFirstTraversal() {
+        Expression expression = parseExpression("(2+3)+(4+5)");
+
+        StringBuilder result = new StringBuilder();
+
+        TreeVisitor visitor = new TreeVisitor() {
+            @Override
+            public void process(Node node) {
+                result.append("<").append(node).append("> ");
+            }
+        };
+
+        visitor.visitBreadthFirst(expression);
+        assertEquals("<(2 + 3) + (4 + 5)> <(2 + 3)> <(4 + 5)> <2 + 3> <4 + 5> <2> <3> <4> <5> ", result.toString());
+    }
+
+    @Test
+    void issue743ConcurrentModificationProblem() {
+        Expression expression = parseExpression("new int[]{1,2,3,4}");
+
+        StringBuilder result = new StringBuilder();
+        TreeVisitor visitor = new TreeVisitor() {
+            @Override
+            public void process(Node node) {
+                if (node instanceof IntegerLiteralExpr) {
+                    node.getParentNode().ifPresent(
+                            parent -> ((ArrayInitializerExpr) parent).getValues().add(new IntegerLiteralExpr("1")));
+                }
+                result.append("<").append(node).append("> ");
+            }
+        };
+        visitor.visitPreOrder(expression);
+        System.out.println(result);
+    }
+
+    @Test
+    void isValidPreOrderTraversal() {
+        StringBuilder result = new StringBuilder();
+        new TreeVisitor() {
+            @Override
+            public void process(Node node) {
+                result.append("<").append(node).append("> ");
+            }
+        }.visitPreOrder(parseExpression("(2+3)+(4+5)"));
+        assertEquals("<(2 + 3) + (4 + 5)> <(2 + 3)> <2 + 3> <2> <3> <(4 + 5)> <4 + 5> <4> <5> ", result.toString());
+    }
+
+    @Test
+    void isValidPostOrderTraversal() {
+        StringBuilder result = new StringBuilder();
+        new TreeVisitor() {
+            @Override
+            public void process(Node node) {
+                result.append("<").append(node).append("> ");
+            }
+        }.visitPostOrder(parseExpression("(2+3)+(4+5)"));
+        assertEquals("<2> <3> <2 + 3> <(2 + 3)> <4> <5> <4 + 5> <(4 + 5)> <(2 + 3) + (4 + 5)> ", result.toString());
+    }
+
+    @Test
+    void preOrderConcurrentModificationIsOk() {
+        new TreeVisitor() {
+            @Override
+            public void process(Node node) {
+                if (node instanceof IntegerLiteralExpr) {
+                    node.getParentNode().ifPresent(
+                            parent -> ((ArrayInitializerExpr) parent).getValues().add(new IntegerLiteralExpr("1")));
+                }
+            }
+        }.visitPreOrder(parseExpression("new int[]{1,2,3,4}"));
+    }
+
+    @Test
+    void postOrderConcurrentModificationIsOk() {
+        new TreeVisitor() {
+            @Override
+            public void process(Node node) {
+                if (node instanceof IntegerLiteralExpr) {
+                    node.getParentNode().ifPresent(
+                            parent -> ((ArrayInitializerExpr) parent).getValues().add(new IntegerLiteralExpr("1")));
+                }
+            }
+        }.visitPostOrder(parseExpression("new int[]{1,2,3,4}"));
+    }
+
+    @Test
+    void parents() {
+        CompilationUnit cu = parse("class X{int x=1;}");
+        SimpleName x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariable(0).getName();
+
+        Node.ParentsVisitor visitor = new Node.ParentsVisitor(x);
+        assertEquals("x = 1", visitor.next().toString());
+        assertEquals("int x = 1;", visitor.next().toString());
+        assertEqualsNoEol("class X {\n" +
+                "\n" +
+                "    int x = 1;\n" +
+                "}", visitor.next().toString());
+        assertEqualsNoEol("class X {\n" +
+                "\n" +
+                "    int x = 1;\n" +
+                "}\n", visitor.next().toString());
+        assertFalse(visitor.hasNext());
+    }
+
+    @Test
+    void isValidDirectChildrenTraversal() {
+        Expression expression = parseExpression("(2+3)+(4+5)");
+
+        StringBuilder result = new StringBuilder();
+
+        TreeVisitor visitor = new TreeVisitor() {
+            @Override
+            public void process(Node node) {
+                result.append("<").append(node).append("> ");
+            }
+        };
+
+        visitor.visitDirectChildren(expression);
+        assertEquals("<(2 + 3)> <(4 + 5)> ", result.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/ClassOrInterfaceDeclarationBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/ClassOrInterfaceDeclarationBuildersTest.java
new file mode 100644
index 0000000..262da05
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/ClassOrInterfaceDeclarationBuildersTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.function.Function;
+
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ClassOrInterfaceDeclarationBuildersTest {
+    CompilationUnit cu;
+
+    @BeforeEach
+    void setup() {
+        cu = new CompilationUnit();
+    }
+
+    @AfterEach
+    void teardown() {
+        cu = null;
+    }
+
+    @Test
+    void testAddExtends() {
+        ClassOrInterfaceDeclaration testClass = cu.addClass("test");
+        testClass.addExtendedType(List.class);
+        assertEquals(1, cu.getImports().size());
+        assertEquals("import " + List.class.getName() + ";" + EOL,
+                cu.getImport(0).toString());
+        assertEquals(1, testClass.getExtendedTypes().size());
+        assertEquals(List.class.getSimpleName(), testClass.getExtendedTypes(0).getNameAsString());
+    }
+
+    @Test
+    void testAddImplements() {
+        ClassOrInterfaceDeclaration testClass = cu.addClass("test");
+        testClass.addImplementedType(Function.class);
+        assertEquals(1, cu.getImports().size());
+        assertEquals("import " + Function.class.getName() + ";" + EOL,
+                cu.getImport(0).toString());
+        assertEquals(1, testClass.getImplementedTypes().size());
+        assertEquals(Function.class.getSimpleName(), testClass.getImplementedTypes(0).getNameAsString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/CompilationUnitBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/CompilationUnitBuildersTest.java
new file mode 100644
index 0000000..382faac
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/CompilationUnitBuildersTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import org.junit.jupiter.api.Test;
+
+import java.lang.annotation.ElementType;
+import java.util.List;
+import java.util.Map;
+
+import static com.github.javaparser.StaticJavaParser.parseImport;
+import static com.github.javaparser.ast.Modifier.Keyword.PRIVATE;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class CompilationUnitBuildersTest {
+    private final CompilationUnit cu = new CompilationUnit();
+
+    @Test
+    void testAddImport() {
+        cu.addImport(Map.class);
+        cu.addImport(Map.class);
+        cu.addImport(List.class);
+        assertEquals(2, cu.getImports().size());
+        cu.addImport("myImport");
+        assertEquals(3, cu.getImports().size());
+        assertEquals("import " + Map.class.getName() + ";" + EOL, cu.getImport(0).toString());
+        assertEquals("import " + List.class.getName() + ";" + EOL, cu.getImport(1).toString());
+        assertEquals("import myImport;" + EOL, cu.getImport(2).toString());
+    }
+
+    @Test
+    void typesInTheJavaLangPackageDoNotNeedExplicitImports() {
+        cu.addImport(String.class);
+        assertEquals(0, cu.getImports().size());
+    }
+
+    @Test
+    void typesInSubPackagesOfTheJavaLangPackageRequireExplicitImports() {
+        cu.addImport(ElementType.class);
+        assertEquals(1, cu.getImports().size());
+        assertEquals("import java.lang.annotation.ElementType;"+ EOL, cu.getImport(0).toString());
+    }
+
+    @Test
+    void doNotAddDuplicateImportsByClass() {
+        cu.addImport(Map.class);
+        cu.addImport(Map.class);
+        assertEquals(1, cu.getImports().size());
+    }
+
+    @Test
+    void doNotAddDuplicateImportsByString() {
+        cu.addImport(Map.class);
+        cu.addImport("java.util.Map");
+        assertEquals(1, cu.getImports().size());
+    }
+
+    @Test
+    void doNotAddDuplicateImportsByStringAndFlags() {
+        cu.addImport(Map.class);
+        cu.addImport("java.util.Map", false, false);
+        assertEquals(1, cu.getImports().size());
+    }
+
+    @Test
+    void doNotAddDuplicateImportsByImportDeclaration() {
+        cu.addImport(Map.class);
+        cu.addImport(parseImport("import java.util.Map;"));
+        assertEquals(1, cu.getImports().size());
+    }
+
+    @Test
+    void testAddImportArrayTypes() {
+        cu.addImport(CompilationUnit[][][].class);
+        cu.addImport(int[][][].class);
+        cu.addImport(Integer[][][].class);
+        cu.addImport(List[][][].class);
+        assertEquals(2, cu.getImports().size());
+        assertEquals("com.github.javaparser.ast.CompilationUnit", cu.getImport(0).getNameAsString());
+        assertEquals("java.util.List", cu.getImport(1).getNameAsString());
+    }
+
+    class testInnerClass {
+
+    }
+
+    @Test
+    void testAddImportAnonymousClass() {
+        cu.addImport(testInnerClass.class);
+        assertEquals("import " + testInnerClass.class.getName().replace("$", ".") + ";" + EOL,
+                cu.getImport(0).toString());
+    }
+
+    @Test
+    void testAddImportInnerClass() {
+        assertThrows(RuntimeException.class, () -> {
+            Object anonymous = new Object(){
+
+            };
+            cu.addImport(anonymous.getClass());
+    });
+}
+
+    @Test
+    void testAddClass() {
+        ClassOrInterfaceDeclaration myClassDeclaration = cu.addClass("testClass", PRIVATE);
+        assertEquals(1, cu.getTypes().size());
+        assertEquals("testClass", cu.getType(0).getNameAsString());
+        assertEquals(ClassOrInterfaceDeclaration.class, cu.getType(0).getClass());
+        assertTrue(myClassDeclaration.isPrivate());
+        assertFalse(myClassDeclaration.isInterface());
+    }
+
+    @Test
+    void testAddInterface() {
+        ClassOrInterfaceDeclaration myInterfaceDeclaration = cu.addInterface("testInterface");
+        assertEquals(1, cu.getTypes().size());
+        assertEquals("testInterface", cu.getType(0).getNameAsString());
+        assertTrue(myInterfaceDeclaration.isPublic());
+        assertEquals(ClassOrInterfaceDeclaration.class, cu.getType(0).getClass());
+        assertTrue(myInterfaceDeclaration.isInterface());
+    }
+
+    @Test
+    void testAddEnum() {
+        EnumDeclaration myEnumDeclaration = cu.addEnum("test");
+        assertEquals(1, cu.getTypes().size());
+        assertEquals("test", cu.getType(0).getNameAsString());
+        assertTrue(myEnumDeclaration.isPublic());
+        assertEquals(EnumDeclaration.class, cu.getType(0).getClass());
+    }
+
+    @Test
+    void testAddAnnotationDeclaration() {
+        AnnotationDeclaration myAnnotationDeclaration = cu.addAnnotationDeclaration("test");
+        assertEquals(1, cu.getTypes().size());
+        assertEquals("test", cu.getType(0).getNameAsString());
+        assertTrue(myAnnotationDeclaration.isPublic());
+        assertEquals(AnnotationDeclaration.class, cu.getType(0).getClass());
+    }
+
+    @Test
+    void testGetClassByName() {
+        assertEquals(cu.addClass("test"), cu.getClassByName("test").get());
+    }
+
+    @Test
+    void testGetInterfaceByName() {
+        assertEquals(cu.addInterface("test"), cu.getInterfaceByName("test").get());
+    }
+
+    @Test
+    void testGetEnumByName() {
+        assertEquals(cu.addEnum("test"), cu.getEnumByName("test").get());
+    }
+
+    @Test
+    void testGetAnnotationDeclarationByName() {
+        assertEquals(cu.addAnnotationDeclaration("test"), cu.getAnnotationDeclarationByName("test").get());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/EnumDeclarationBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/EnumDeclarationBuildersTest.java
new file mode 100644
index 0000000..2840a53
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/EnumDeclarationBuildersTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import org.junit.jupiter.api.Test;
+
+import java.util.function.Function;
+
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class EnumDeclarationBuildersTest {
+    private final CompilationUnit cu = new CompilationUnit();
+
+    @Test
+    void testAddImplements() {
+        EnumDeclaration testEnum = cu.addEnum("test");
+        testEnum.addImplementedType(Function.class);
+        assertEquals(1, cu.getImports().size());
+        assertEquals("import " + Function.class.getName() + ";" + EOL,
+                cu.getImport(0).toString());
+        assertEquals(1, testEnum.getImplementedTypes().size());
+        assertEquals(Function.class.getSimpleName(), testEnum.getImplementedTypes(0).getNameAsString());
+    }
+
+    @Test
+    void testAddEnumConstant() {
+        EnumDeclaration testEnum = cu.addEnum("test");
+        testEnum.addEnumConstant("MY_ENUM_CONSTANT");
+        assertEquals(1, testEnum.getEntries().size());
+        assertEquals("MY_ENUM_CONSTANT", testEnum.getEntry(0).getNameAsString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/FieldDeclarationBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/FieldDeclarationBuildersTest.java
new file mode 100644
index 0000000..4ce066e
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/FieldDeclarationBuildersTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.github.javaparser.ast.type.PrimitiveType.intType;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class FieldDeclarationBuildersTest {
+    private final CompilationUnit cu = new CompilationUnit();
+    private ClassOrInterfaceDeclaration testClass = cu.addClass("testClass");
+    private EnumDeclaration testEnum = cu.addEnum("testEnum");
+
+    @Test
+    void testOrphanFieldGetter() {
+        assertThrows(IllegalStateException.class, () -> new FieldDeclaration().createGetter());
+    }
+
+    @Test
+    void testOrphanFieldSetter() {
+        assertThrows(IllegalStateException.class, () -> new FieldDeclaration().createSetter());
+    }
+
+    @Test
+    void testCreateGetterInAClass() {
+        testClass.addPrivateField(int.class, "myField").createGetter();
+        assertEquals(2, testClass.getMembers().size());
+        assertEquals(MethodDeclaration.class, testClass.getMember(1).getClass());
+        List<MethodDeclaration> methodsWithName = testClass.getMethodsByName("getMyField");
+        assertEquals(1, methodsWithName.size());
+        MethodDeclaration getter = methodsWithName.get(0);
+        assertEquals("getMyField", getter.getNameAsString());
+        assertEquals("int", getter.getType().toString());
+        assertEquals(ReturnStmt.class, getter.getBody().get().getStatement(0).getClass());
+    }
+
+    @Test
+    void testCreateSetterInAClass() {
+        testClass.addPrivateField(int.class, "myField").createSetter();
+        assertEquals(2, testClass.getMembers().size());
+        assertEquals(MethodDeclaration.class, testClass.getMember(1).getClass());
+        List<MethodDeclaration> methodsWithName = testClass.getMethodsByName("setMyField");
+        assertEquals(1, methodsWithName.size());
+        MethodDeclaration setter = methodsWithName.get(0);
+        assertEquals("setMyField", setter.getNameAsString());
+        assertEquals("int", setter.getParameter(0).getType().toString());
+        assertEquals(ExpressionStmt.class, setter.getBody().get().getStatement(0).getClass());
+        assertEquals("this.myField = myField;", setter.getBody().get().getStatement(0).toString());
+    }
+
+    @Test
+    void testCreateGetterInEnum() {
+        testEnum.addPrivateField(int.class, "myField").createGetter();
+        assertEquals(2, testEnum.getMembers().size());
+        assertEquals(MethodDeclaration.class, testEnum.getMember(1).getClass());
+        List<MethodDeclaration> methodsWithName = testEnum.getMethodsByName("getMyField");
+        assertEquals(1, methodsWithName.size());
+        MethodDeclaration getter = methodsWithName.get(0);
+        assertEquals("getMyField", getter.getNameAsString());
+        assertEquals("int", getter.getType().toString());
+        assertEquals(ReturnStmt.class, getter.getBody().get().getStatement(0).getClass());
+    }
+
+    @Test
+    void testCreateSetterInEnum() {
+        testEnum.addPrivateField(int.class, "myField").createSetter();
+        assertEquals(2, testEnum.getMembers().size());
+        assertEquals(MethodDeclaration.class, testEnum.getMember(1).getClass());
+        List<MethodDeclaration> methodsWithName = testEnum.getMethodsByName("setMyField");
+        assertEquals(1, methodsWithName.size());
+        MethodDeclaration setter = methodsWithName.get(0);
+        assertEquals("setMyField", setter.getNameAsString());
+        assertEquals("int", setter.getParameter(0).getType().toString());
+        assertEquals(ExpressionStmt.class, setter.getBody().get().getStatement(0).getClass());
+        assertEquals("this.myField = myField;", setter.getBody().get().getStatement(0).toString());
+    }
+
+    @Test
+    void testCreateGetterWithANonValidField() {
+        assertThrows(IllegalStateException.class, () -> {
+            FieldDeclaration myPrivateField = testClass.addPrivateField(int.class, "myField");
+        myPrivateField.getVariables().add(new VariableDeclarator(intType(), "secondField"));
+        myPrivateField.createGetter();
+    });
+        }
+
+    @Test
+    void testCreateSetterWithANonValidField() {
+        assertThrows(IllegalStateException.class, () -> {
+            FieldDeclaration myPrivateField = testClass.addPrivateField(int.class, "myField");
+        myPrivateField.getVariables().add(new VariableDeclarator(intType(), "secondField"));
+        myPrivateField.createSetter();
+    });
+        }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithAnnotationsBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithAnnotationsBuildersTest.java
new file mode 100644
index 0000000..0380269
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithAnnotationsBuildersTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.expr.NormalAnnotationExpr;
+import com.github.javaparser.ast.expr.SimpleName;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NodeWithAnnotationsBuildersTest {
+    private CompilationUnit cu = new CompilationUnit();
+    private ClassOrInterfaceDeclaration testClass = cu.addClass("testClass");
+
+    @interface hey {
+
+    }
+
+    @Test
+    void testAddAnnotation() {
+        NormalAnnotationExpr annotation = testClass.addAndGetAnnotation(hey.class);
+        assertEquals("import com.github.javaparser.builders.NodeWithAnnotationsBuildersTest.hey;", cu.getImport(0).toString().trim());
+        assertEquals(1, testClass.getAnnotations().size());
+        assertEquals(annotation, testClass.getAnnotation(0));
+        assertEquals(NormalAnnotationExpr.class, testClass.getAnnotation(0).getClass());
+    }
+
+    @Test
+    void testAddMarkerAnnotation() {
+        testClass.addMarkerAnnotation("test");
+        assertEquals(1, testClass.getAnnotations().size());
+    }
+
+    @Test
+    void testAddSingleMemberAnnotation() {
+        testClass.addSingleMemberAnnotation("test", "value");
+        assertEquals(1, testClass.getAnnotations().size());
+        assertEquals("value", testClass.getAnnotation(0).asSingleMemberAnnotationExpr().getMemberValue().toString());
+    }
+
+    @Test
+    void testAddSingleMemberAnnotation2() {
+        testClass.addSingleMemberAnnotation(hey.class, new NameExpr(new SimpleName("value")));
+        assertEquals(1, testClass.getAnnotations().size());
+        assertEquals("value", testClass.getAnnotation(0).asSingleMemberAnnotationExpr().getMemberValue().toString());
+    }
+
+    @Test
+    void testIsAnnotationPresent() {
+        testClass.addMarkerAnnotation(hey.class);
+        assertTrue(testClass.isAnnotationPresent(hey.class));
+    }
+
+    @Test
+    void testGetAnnotationByName() {
+        NormalAnnotationExpr annotation = testClass.addAndGetAnnotation(hey.class);
+        assertEquals(annotation, testClass.getAnnotationByName("hey").get());
+    }
+
+    @Test
+    void testGetAnnotationByClass() {
+        NormalAnnotationExpr annotation = testClass.addAndGetAnnotation(hey.class);
+        assertEquals(annotation, testClass.getAnnotationByClass(hey.class).get());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithMembersBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithMembersBuildersTest.java
new file mode 100644
index 0000000..14f1de2
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithMembersBuildersTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.ast.Modifier.Keyword.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+class NodeWithMembersBuildersTest {
+    private final CompilationUnit cu = new CompilationUnit();
+    private final ClassOrInterfaceDeclaration classDeclaration = cu.addClass("test");
+
+    @Test
+    void testAddField() {
+        FieldDeclaration addField = classDeclaration.addField(int.class, "fieldName", PRIVATE);
+        assertEquals(1, classDeclaration.getMembers().size());
+        assertEquals(addField, classDeclaration.getMember(0));
+        assertEquals("fieldName", addField.getVariable(0).getNameAsString());
+    }
+
+    @Test
+    void testAddMethod() {
+        MethodDeclaration addMethod = classDeclaration.addMethod("foo", PUBLIC);
+        assertEquals(1, classDeclaration.getMembers().size());
+        assertEquals(addMethod, classDeclaration.getMember(0));
+        assertEquals("foo", addMethod.getNameAsString());
+    }
+
+    @Test
+    void testAddCtor() {
+        ConstructorDeclaration addCtor = classDeclaration.addConstructor(PUBLIC);
+        assertEquals(1, classDeclaration.getMembers().size());
+        assertEquals(addCtor, classDeclaration.getMember(0));
+        assertEquals(classDeclaration.getName(), addCtor.getName());
+    }
+
+    @Test
+    void testAddInitializers() {
+        classDeclaration.addInitializer();
+        assertEquals(1, classDeclaration.getMembers().size());
+        assertEquals(InitializerDeclaration.class, classDeclaration.getMember(0).getClass());
+
+        classDeclaration.addStaticInitializer();
+        assertEquals(2, classDeclaration.getMembers().size());
+        assertEquals(InitializerDeclaration.class, classDeclaration.getMember(0).getClass());
+    }
+
+    @Test
+    void testGetMethodsWithName() {
+        MethodDeclaration addMethod = classDeclaration.addMethod("foo", PUBLIC);
+        MethodDeclaration addMethod2 = classDeclaration.addMethod("foo", PUBLIC).addParameter(int.class, "overload");
+        List<MethodDeclaration> methodsByName = classDeclaration.getMethodsByName("foo");
+        assertEquals(2, methodsByName.size());
+        assertTrue(methodsByName.contains(addMethod));
+        assertTrue(methodsByName.contains(addMethod2));
+    }
+
+    @Test
+    void testGetMethods() {
+        MethodDeclaration addMethod = classDeclaration.addMethod("foo", PUBLIC);
+        MethodDeclaration addMethod2 = classDeclaration.addMethod("foo", PUBLIC).addParameter(int.class, "overload");
+
+        List<MethodDeclaration> methods = classDeclaration.getMethods();
+
+        assertEquals(2, methods.size());
+        assertTrue(methods.contains(addMethod));
+        assertTrue(methods.contains(addMethod2));
+    }
+
+    @Test
+    void testGetMethodsWithParameterTypes() {
+        classDeclaration.addMethod("foo", PUBLIC);
+        MethodDeclaration addMethod2 = classDeclaration.addMethod("foo", PUBLIC).addParameter(int.class, "overload");
+        ClassOrInterfaceType type = parseClassOrInterfaceType("List");
+        type.setTypeArguments(parseClassOrInterfaceType("String"));
+        MethodDeclaration methodWithListParam = classDeclaration.addMethod("fooList", PUBLIC).addParameter(type, "overload");
+        MethodDeclaration addMethod3 = classDeclaration.addMethod("foo2", PUBLIC).addParameter(int.class, "overload");
+
+        List<MethodDeclaration> methodsByParam = classDeclaration.getMethodsByParameterTypes(int.class);
+        assertEquals(2, methodsByParam.size());
+        assertTrue(methodsByParam.contains(addMethod2));
+        assertTrue(methodsByParam.contains(addMethod3));
+        List<MethodDeclaration> methodsByParam2 = classDeclaration.getMethodsByParameterTypes("List<String>");
+        assertEquals(1, methodsByParam2.size());
+        assertTrue(methodsByParam2.contains(methodWithListParam));
+    }
+
+    @Test
+    void testGetFieldWithName() {
+        FieldDeclaration addField = classDeclaration.addField(int.class, "fieldName", PRIVATE);
+        classDeclaration.addField(float.class, "secondField", PRIVATE);
+        FieldDeclaration fieldByName = classDeclaration.getFieldByName("fieldName").get();
+        assertEquals(addField, fieldByName);
+    }
+
+    @Test
+    void testGetFields() {
+        FieldDeclaration firstField = classDeclaration.addField(int.class, "fieldName", PRIVATE);
+        FieldDeclaration secondField = classDeclaration.addField(float.class, "secondField", PRIVATE);
+
+        List<FieldDeclaration> fields = classDeclaration.getFields();
+
+        assertTrue(fields.contains(firstField));
+        assertTrue(fields.contains(secondField));
+    }
+
+    @Test
+    void testAddPrivateFieldWithType(){
+        CompilationUnit compilationUnit = new CompilationUnit();
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = compilationUnit.addClass("Person");
+        classOrInterfaceDeclaration.addPrivateField(parseType("java.lang.String"), "name");
+
+        assertNotNull(classOrInterfaceDeclaration.getFields());
+        assertEquals(1, classOrInterfaceDeclaration.getFields().size());
+
+        FieldDeclaration fieldDeclaration = classOrInterfaceDeclaration.getFields().get(0);
+        assertEquals(PRIVATE, fieldDeclaration.getModifiers().iterator().next().getKeyword());
+        assertEquals("java.lang.String",fieldDeclaration.getVariables().get(0).getType().toString());
+        assertEquals("name",fieldDeclaration.getVariables().get(0).getName().toString());
+    }
+
+    @Test
+    void testAddPublicFieldWithType(){
+        CompilationUnit compilationUnit = new CompilationUnit();
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = compilationUnit.addClass("Person");
+        classOrInterfaceDeclaration.addPublicField(parseType("java.lang.String"), "name");
+
+        assertNotNull(classOrInterfaceDeclaration.getFields());
+        assertEquals(1, classOrInterfaceDeclaration.getFields().size());
+
+        FieldDeclaration fieldDeclaration = classOrInterfaceDeclaration.getFields().get(0);
+        assertEquals(PUBLIC, fieldDeclaration.getModifiers().iterator().next().getKeyword());
+        assertEquals("java.lang.String",fieldDeclaration.getVariables().get(0).getType().toString());
+        assertEquals("name",fieldDeclaration.getVariables().get(0).getName().toString());
+    }
+
+    @Test
+    void testAddProtectedFieldWithType(){
+        CompilationUnit compilationUnit = new CompilationUnit();
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = compilationUnit.addClass("Person");
+        classOrInterfaceDeclaration.addProtectedField(parseType("java.lang.String"), "name");
+
+        assertNotNull(classOrInterfaceDeclaration.getFields());
+        assertEquals(1, classOrInterfaceDeclaration.getFields().size());
+
+        FieldDeclaration fieldDeclaration = classOrInterfaceDeclaration.getFields().get(0);
+        assertEquals(PROTECTED, fieldDeclaration.getModifiers().iterator().next().getKeyword());
+        assertEquals("java.lang.String",fieldDeclaration.getVariables().get(0).getType().toString());
+        assertEquals("name",fieldDeclaration.getVariables().get(0).getName().toString());
+    }
+
+    @Test
+    void testClassWithInitializersWithString(){
+        CompilationUnit compilationUnit = new CompilationUnit();
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = compilationUnit.addClass("Person");
+        classOrInterfaceDeclaration.addFieldWithInitializer(
+                "java.lang.String",
+                "name",
+                parseExpression("John"),
+                PUBLIC);
+        assertNotNull(classOrInterfaceDeclaration.getFields());
+        assertEquals(1, classOrInterfaceDeclaration.getFields().size());
+
+        FieldDeclaration fieldDeclaration = classOrInterfaceDeclaration.getFields().get(0);
+        assertEquals(PUBLIC, fieldDeclaration.getModifiers().iterator().next().getKeyword());
+        assertEquals("java.lang.String",fieldDeclaration.getVariables().get(0).getType().toString());
+        assertEquals("name",fieldDeclaration.getVariables().get(0).getName().toString());
+        assertEquals("John",fieldDeclaration.getVariables().get(0).getInitializer().get().toString());
+    }
+
+    @Test
+    void testClassWithInitializersWithClass(){
+        CompilationUnit compilationUnit = new CompilationUnit();
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = compilationUnit.addClass("Person");
+        classOrInterfaceDeclaration.addFieldWithInitializer(
+                List.class,
+                "skills",
+                parseExpression("new ArrayList()"),
+                PUBLIC);
+        assertNotNull(classOrInterfaceDeclaration.getFields());
+        assertEquals(1, classOrInterfaceDeclaration.getFields().size());
+
+        FieldDeclaration fieldDeclaration = classOrInterfaceDeclaration.getFields().get(0);
+        assertEquals(PUBLIC, fieldDeclaration.getModifiers().iterator().next().getKeyword());
+        assertEquals("List",fieldDeclaration.getVariables().get(0).getType().toString());
+        assertEquals("skills",fieldDeclaration.getVariables().get(0).getName().toString());
+        assertEquals("new ArrayList()",fieldDeclaration.getVariables().get(0).getInitializer().get().toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithParametersBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithParametersBuildersTest.java
new file mode 100644
index 0000000..f0da0e1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithParametersBuildersTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.Parameter;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class NodeWithParametersBuildersTest {
+    private final CompilationUnit cu = new CompilationUnit();
+
+    @Test
+    void testAddParameter() {
+        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", PUBLIC);
+        addMethod.addParameter(int.class, "yay");
+        Parameter myNewParam = addMethod.addAndGetParameter(List.class, "myList");
+        assertEquals(1, cu.getImports().size());
+        assertEquals("import " + List.class.getName() + ";" + EOL, cu.getImport(0).toString());
+        assertEquals(2, addMethod.getParameters().size());
+        assertEquals("yay", addMethod.getParameter(0).getNameAsString());
+        assertEquals("List", addMethod.getParameter(1).getType().toString());
+        assertEquals(myNewParam, addMethod.getParameter(1));
+    }
+
+    @Test
+    void testGetParamByName() {
+        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", PUBLIC);
+        Parameter addAndGetParameter = addMethod.addAndGetParameter(int.class, "yay");
+        assertEquals(addAndGetParameter, addMethod.getParameterByName("yay").get());
+    }
+
+    @Test
+    void testGetParamByType() {
+        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", PUBLIC);
+        Parameter addAndGetParameter = addMethod.addAndGetParameter(int.class, "yay");
+        assertEquals(addAndGetParameter, addMethod.getParameterByType("int").get());
+        assertEquals(addAndGetParameter, addMethod.getParameterByType(int.class).get());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithThrownExceptionsBuildersTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithThrownExceptionsBuildersTest.java
new file mode 100644
index 0000000..31d3b91
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/builders/NodeWithThrownExceptionsBuildersTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.builders;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NodeWithThrownExceptionsBuildersTest {
+    private final CompilationUnit cu = new CompilationUnit();
+
+    @Test
+    void testThrows() {
+        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", PUBLIC);
+        addMethod.addThrownException(IllegalStateException.class);
+        assertEquals(1, addMethod.getThrownExceptions().size());
+        assertTrue(addMethod.isThrown(IllegalStateException.class));
+        addMethod.addThrownException(parseClassOrInterfaceType("Test"));
+        assertEquals(2, addMethod.getThrownExceptions().size());
+        assertEquals("Test", addMethod.getThrownException(1).toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/JavadocExtractorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/JavadocExtractorTest.java
new file mode 100644
index 0000000..aa32934
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/JavadocExtractorTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.javadoc;
+
+import com.github.javaparser.ParseProblemException;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.comments.JavadocComment;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.nio.charset.StandardCharsets;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+
+class JavadocExtractorTest {
+
+    @Test
+    void canParseAllJavadocsInJavaParser() throws FileNotFoundException {
+        processDir(new File(".."));
+    }
+
+    private void processFile(File file) throws FileNotFoundException {
+        try {
+            CompilationUnit cu = parse(file);
+            new VoidVisitorAdapter<Object>() {
+                @Override
+                public void visit(JavadocComment n, Object arg) {
+                    super.visit(n, arg);
+                    n.parse();
+                }
+            }.visit(cu, null);
+        } catch (ParseProblemException e) {
+            System.err.println("ERROR PROCESSING "+ file);
+        }
+    }
+
+    private void processDir(File dir) throws FileNotFoundException {
+        for (File child : dir.listFiles()) {
+            if (child.isFile() && child.getName().endsWith(".java")) {
+                processFile(child);
+            } else if (child.isDirectory()) {
+                processDir(child);
+            }
+        }
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/JavadocTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/JavadocTest.java
new file mode 100644
index 0000000..857f0ae
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/JavadocTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.javadoc;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.comments.JavadocComment;
+import com.github.javaparser.javadoc.description.JavadocDescription;
+import com.github.javaparser.javadoc.description.JavadocDescriptionElement;
+import com.github.javaparser.javadoc.description.JavadocInlineTag;
+import com.github.javaparser.javadoc.description.JavadocSnippet;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseJavadoc;
+import static com.github.javaparser.javadoc.description.JavadocInlineTag.Type.*;
+import static com.github.javaparser.utils.Utils.EOL;
+import static java.util.stream.Collectors.toList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class JavadocTest {
+
+    @Test
+    void toTextForEmptyJavadoc() {
+        Javadoc javadoc = new Javadoc(new JavadocDescription());
+        assertEquals("", javadoc.toText());
+    }
+
+    @Test
+    void toTextForJavadocWithTwoLinesOfJustDescription() {
+        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
+        assertEquals("first line" + EOL + "second line" + EOL, javadoc.toText());
+    }
+
+    @Test
+    void toTextForJavadocWithTwoLinesOfJustDescriptionAndOneBlockTag() {
+        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
+        javadoc.addBlockTag("foo", "something useful");
+        assertEquals("first line" + EOL + "second line" + EOL + EOL + "@foo something useful" + EOL, javadoc.toText());
+    }
+
+    @Test
+    void toCommentForEmptyJavadoc() {
+        Javadoc javadoc = new Javadoc(new JavadocDescription());
+        assertEquals(new JavadocComment("" + EOL + "\t\t "), javadoc.toComment("\t\t"));
+    }
+
+    @Test
+    void toCommentorJavadocWithTwoLinesOfJustDescription() {
+        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
+        assertEquals(new JavadocComment("" + EOL + "\t\t * first line" + EOL + "\t\t * second line" + EOL + "\t\t "), javadoc.toComment("\t\t"));
+    }
+
+    @Test
+    void toCommentForJavadocWithTwoLinesOfJustDescriptionAndOneBlockTag() {
+        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
+        javadoc.addBlockTag("foo", "something useful");
+        assertEquals(new JavadocComment("" + EOL + "\t\t * first line" + EOL + "\t\t * second line" + EOL + "\t\t * " + EOL + "\t\t * @foo something useful" + EOL + "\t\t "), javadoc.toComment("\t\t"));
+    }
+
+    @Test
+    void descriptionAndBlockTagsAreRetrievable() {
+        Javadoc javadoc = parseJavadoc("first line" + EOL + "second line" + EOL + EOL + "@param node a node" + EOL + "@return result the result");
+        assertEquals("first line" + EOL + "second line", javadoc.getDescription().toText());
+        assertEquals(2, javadoc.getBlockTags().size());
+    }
+
+    @Test
+    void inlineTagsAreParsable() {
+        String docText =
+                "Returns the {@link TOFilename}s of all files that existed during the requested" + EOL +
+                        "{@link TOVersion}. Set {@systemProperty JAVA_HOME} correctly." + EOL +
+                        "" + EOL +
+                        "@param versionID the id of the {@link TOVersion}." + EOL +
+                        "@return the filenames" + EOL +
+                        "@throws InvalidIDException if the {@link IPersistence} doesn't recognize the given versionID." + EOL;
+        Javadoc javadoc = parseJavadoc(docText);
+
+        List<JavadocInlineTag> inlineTags = javadoc.getDescription().getElements().stream()
+                .filter(element -> element instanceof JavadocInlineTag)
+                .map(element -> (JavadocInlineTag) element)
+                .collect(toList());
+
+        assertEquals("link", inlineTags.get(0).getName());
+        assertEquals(" TOFilename", inlineTags.get(0).getContent());
+        assertEquals(LINK, inlineTags.get(0).getType());
+        assertEquals("link", inlineTags.get(1).getName());
+        assertEquals(" TOVersion", inlineTags.get(1).getContent());
+        assertEquals(LINK, inlineTags.get(1).getType());
+        assertEquals("systemProperty", inlineTags.get(2).getName());
+        assertEquals(" JAVA_HOME", inlineTags.get(2).getContent());
+        assertEquals(SYSTEM_PROPERTY, inlineTags.get(2).getType());
+        
+        String javadocText = javadoc.toText();
+        assertTrue(javadocText.contains("{@link TOVersion}"));
+    }
+
+    @Test
+    void emptyLinesBetweenBlockTagsGetsFiltered() {
+        String comment = " * The type of the Object to be mapped." + EOL +
+                " * This interface maps the given Objects to existing ones in the database and" + EOL +
+                " * saves them." + EOL +
+                " * " + EOL +
+                " * @author censored" + EOL +
+                " * " + EOL +
+                " * @param <T>" + EOL;
+        Javadoc javadoc = parseJavadoc(comment);
+        assertEquals(2, javadoc.getBlockTags().size());
+    }
+
+    @Test
+    void blockTagModificationWorks() {
+        Javadoc javadoc = new Javadoc(new JavadocDescription());
+
+        assertEquals(0, javadoc.getBlockTags().size());
+        JavadocBlockTag blockTag = new JavadocBlockTag(JavadocBlockTag.Type.RETURN, "a value");
+        javadoc.addBlockTag(blockTag);
+
+        assertEquals(1, javadoc.getBlockTags().size());
+        assertEquals(blockTag, javadoc.getBlockTags().get(0));
+
+        assertEquals(blockTag, javadoc.getBlockTags().remove(0));
+        assertEquals(0, javadoc.getBlockTags().size());
+    }
+
+    @Test
+    void descriptionModificationWorks() {
+        JavadocDescription description = new JavadocDescription();
+
+        assertEquals(0, description.getElements().size());
+
+        JavadocDescriptionElement inlineTag = new JavadocInlineTag("inheritDoc", INHERIT_DOC, "");
+        assertTrue(description.addElement(inlineTag));
+
+        assertEquals(1, description.getElements().size());
+        assertEquals(inlineTag, description.getElements().get(0));
+
+        assertEquals(inlineTag, description.getElements().remove(0));
+        assertEquals(0, description.getElements().size());
+    }
+
+    @Test
+    void issue1533() {
+        CompilationUnit compilationUnit = parse("/** hallo {@link Foo} welt */ public interface Foo extends Comparable { }");
+        List<JavadocDescriptionElement> elements = compilationUnit.getType(0).getJavadoc().get().getDescription().getElements();
+        assertEquals(3, elements.size());
+        assertEquals(new JavadocSnippet("hallo "), elements.get(0));
+        assertEquals(new JavadocInlineTag("link", LINK, " Foo"), elements.get(1));
+        assertEquals(new JavadocSnippet(" welt"), elements.get(2));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/description/JavadocInlineTagTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/description/JavadocInlineTagTest.java
new file mode 100644
index 0000000..f7d1cd3
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/javadoc/description/JavadocInlineTagTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2017 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.javadoc.description;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class JavadocInlineTagTest {
+
+    @Test
+    void javadocInlineTagShouldPersistCustomTagNames() {
+        String tag = JavadocInlineTag.fromText("{@foo something}").toText();
+
+        assertEquals(tag, "{@foo something}");
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/manual/BulkParseTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/manual/BulkParseTest.java
new file mode 100644
index 0000000..f4eab27
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/manual/BulkParseTest.java
@@ -0,0 +1,145 @@
+package com.github.javaparser.manual;
+
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.Problem;
+import com.github.javaparser.utils.CodeGenerationUtils;
+import com.github.javaparser.utils.Log;
+import com.github.javaparser.utils.SourceRoot;
+import com.github.javaparser.utils.SourceZip;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
+import static com.github.javaparser.utils.CodeGenerationUtils.*;
+import static com.github.javaparser.utils.CodeGenerationUtils.f;
+import static com.github.javaparser.utils.SourceRoot.Callback.Result.DONT_SAVE;
+import static com.github.javaparser.utils.TestUtils.download;
+import static com.github.javaparser.utils.TestUtils.temporaryDirectory;
+import static java.util.Comparator.comparing;
+
+class BulkParseTest {
+    /**
+     * Running this will download a version of the OpenJDK, unzip it, and parse it. If it throws a stack overflow
+     * exception, increase the JVM's stack size.
+     */
+    public static void main(String[] args) throws IOException {
+        Log.setAdapter(new Log.StandardOutStandardErrorAdapter());
+        // This contains all kinds of test cases so it will lead to a lot of errors:
+        new BulkParseTest().parseOpenJdkLangToolsRepository();
+        // This contains the JDK source code, so it should have zero errors:
+        new BulkParseTest().parseJdkSrcZip();
+    }
+
+    private void parseOpenJdkLangToolsRepository() throws IOException {
+        Path workdir = mavenModuleRoot(BulkParseTest.class).resolve(Paths.get(temporaryDirectory(), "javaparser_bulkparsetest"));
+        workdir.toFile().mkdirs();
+        Path openJdkZipPath = workdir.resolve("langtools.zip");
+        if (Files.notExists(openJdkZipPath)) {
+            Log.info("Downloading JDK langtools");
+            /* Found by choosing a tag here: http://hg.openjdk.java.net/jdk9/jdk9/langtools/tags
+             then copying the "zip" link to the line below: */
+            download(new URL("http://hg.openjdk.java.net/jdk10/jdk10/langtools/archive/19293ea3999f.zip"), openJdkZipPath);
+        }
+        bulkTest(new SourceZip(openJdkZipPath), "openjdk_src_repo_test_results.txt", new ParserConfiguration().setLanguageLevel(JAVA_10));
+    }
+
+    private void parseJdkSrcZip() throws IOException {
+        // This is where Ubuntu stores the contents of package openjdk-8-src
+        Path path = Paths.get("/usr/lib/jvm/openjdk-9/src.zip");
+        bulkTest(new SourceZip(path), "openjdk_src_zip_test_results.txt", new ParserConfiguration().setLanguageLevel(JAVA_9));
+    }
+
+    @BeforeEach
+    void startLogging() {
+        Log.setAdapter(new Log.StandardOutStandardErrorAdapter());
+    }
+
+    @AfterEach
+    void stopLogging() {
+        Log.setAdapter(new Log.SilentAdapter());
+    }
+
+    @Test
+    void parseOwnSourceCode() throws IOException {
+        String[] roots = new String[]{
+                "javaparser-core/src/main/java",
+                "javaparser-core-testing/src/test/java",
+                "javaparser-core-generators/src/main/java",
+                "javaparser-core-metamodel-generator/src/main/java",
+                "javaparser-symbol-solver-core/src/main/java",
+                "javaparser-symbol-solver-logic/src/main/java",
+                "javaparser-symbol-solver-model/src/main/java",
+                "javaparser-symbol-solver-testing/src/test/java"
+        };
+        for (String root : roots) {
+            bulkTest(
+                    new SourceRoot(mavenModuleRoot(BulkParseTest.class).resolve("..").resolve(root)),
+                    "javaparser_test_results_" + root.replace("-", "_").replace("/", "_") + ".txt",
+                    new ParserConfiguration().setLanguageLevel(BLEEDING_EDGE));
+        }
+    }
+
+    public void bulkTest(SourceRoot sourceRoot, String testResultsFileName, ParserConfiguration configuration) throws IOException {
+        sourceRoot.setParserConfiguration(configuration);
+        TreeMap<Path, List<Problem>> results = new TreeMap<>(comparing(o -> o.toString().toLowerCase()));
+        sourceRoot.parseParallelized((localPath, absolutePath, result) -> {
+            if (!localPath.toString().contains("target")) {
+                if (!result.isSuccessful()) {
+                    results.put(localPath, result.getProblems());
+                }
+            }
+            return DONT_SAVE;
+        });
+        writeResults(results, testResultsFileName);
+    }
+
+    public void bulkTest(SourceZip sourceRoot, String testResultsFileName, ParserConfiguration configuration) throws IOException {
+        sourceRoot.setParserConfiguration(configuration);
+        TreeMap<Path, List<Problem>> results = new TreeMap<>(comparing(o -> o.toString().toLowerCase()));
+        sourceRoot.parse((path, result) -> {
+            if (!path.toString().contains("target")) {
+                if (!result.isSuccessful()) {
+                    results.put(path, result.getProblems());
+                }
+            }
+        });
+        writeResults(results, testResultsFileName);
+    }
+
+    private void writeResults(TreeMap<Path, List<Problem>> results, String testResultsFileName) throws IOException {
+        Log.info("Writing results...");
+
+        Path testResults = mavenModuleRoot(BulkParseTest.class).resolve(Paths.get("..", "javaparser-core-testing", "src", "test", "resources", "com", "github", "javaparser", "bulk_test_results")).normalize();
+        testResults.toFile().mkdirs();
+        testResults = testResults.resolve(testResultsFileName);
+
+        int problemTotal = 0;
+        try (BufferedWriter writer = Files.newBufferedWriter(testResults)) {
+            for (Map.Entry<Path, List<Problem>> file : results.entrySet()) {
+                writer.write(file.getKey().toString().replace("\\", "/"));
+                writer.newLine();
+                for (Problem problem : file.getValue()) {
+                    writer.write(problem.getVerboseMessage());
+                    writer.newLine();
+                    problemTotal++;
+                }
+                writer.newLine();
+            }
+            writer.write(f("%s problems in %s files", problemTotal, results.size()));
+        }
+
+        Path finalTestResults = testResults;
+        Log.info("Results are in %s", () -> finalTestResults);
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/metamodel/BaseNodeMetaModelTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/metamodel/BaseNodeMetaModelTest.java
new file mode 100644
index 0000000..0c2711a
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/metamodel/BaseNodeMetaModelTest.java
@@ -0,0 +1,25 @@
+package com.github.javaparser.metamodel;
+
+import com.github.javaparser.ast.expr.StringLiteralExpr;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class TestMetaModel extends BaseNodeMetaModel {
+
+    public TestMetaModel() {
+        super(Optional.empty(), StringLiteralExpr.class, "stri", "com.japa", true, true);
+    }
+}
+
+class BaseNodeMetaModelTest {
+    @Test
+    void testGetters() {
+        TestMetaModel test = new TestMetaModel();
+
+        assertEquals("testMetaModel", test.getMetaModelFieldName());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/metamodel/PropertyMetaModelTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/metamodel/PropertyMetaModelTest.java
new file mode 100644
index 0000000..322c950
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/metamodel/PropertyMetaModelTest.java
@@ -0,0 +1,45 @@
+package com.github.javaparser.metamodel;
+
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.body.BodyDeclaration;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class PropertyMetaModelTest {
+    @Test
+    void whenPropertyIsVerySimpleThenTypeInfoIsCorrect() {
+        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", int.class, Optional.empty(), false, false, false, false);
+        assertEquals("int", bert.getTypeName());
+        assertEquals("int", bert.getTypeNameGenerified());
+        assertEquals("int", bert.getTypeNameForGetter());
+        assertEquals("int", bert.getTypeNameForSetter());
+    }
+
+    @Test
+    void whenPropertyIsVeryComplexThenTypeInfoIsCorrect() {
+        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", BodyDeclaration.class, Optional.empty(), true, false, true, true);
+        assertEquals("BodyDeclaration", bert.getTypeName());
+        assertEquals("BodyDeclaration<?>", bert.getTypeNameGenerified());
+        assertEquals("Optional<NodeList<BodyDeclaration<?>>>", bert.getTypeNameForGetter());
+        assertEquals("NodeList<BodyDeclaration<?>>", bert.getTypeNameForSetter());
+    }
+
+    @Test
+    void whenPropertyIsANodeListThenTypeInfoIsCorrect() {
+        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", Modifier.class, Optional.empty(), false, false, true, false);
+        assertEquals("Modifier", bert.getTypeName());
+        assertEquals("Modifier", bert.getTypeNameGenerified());
+        assertEquals("NodeList<Modifier>", bert.getTypeNameForGetter());
+        assertEquals("NodeList<Modifier>", bert.getTypeNameForSetter());
+    }
+
+    @Test
+    void metaModelFieldName() {
+        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", Modifier.class, Optional.empty(), false, false, false, false);
+        assertEquals("bertPropertyMetaModel", bert.getMetaModelFieldName());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/modules/ModuleDeclarationTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/modules/ModuleDeclarationTest.java
new file mode 100644
index 0000000..6105fa3
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/modules/ModuleDeclarationTest.java
@@ -0,0 +1,220 @@
+package com.github.javaparser.modules;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
+import com.github.javaparser.ast.modules.*;
+import com.github.javaparser.printer.ConcreteSyntaxModel;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.GeneratedJavaParserConstants.IDENTIFIER;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_9;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.StaticJavaParser.parseName;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+class ModuleDeclarationTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
+
+    private CompilationUnit parse(String code) {
+        ParseResult<CompilationUnit> result = javaParser.parse(ParseStart.COMPILATION_UNIT, provider(code));
+        if(!result.isSuccessful()){
+            System.err.println(result);
+        }
+        return result.getResult().get();
+    }
+
+    @Test
+    void moduleInfoKeywordsAreSeenAsIdentifiers() {
+        CompilationUnit cu = parse("class module { }");
+        JavaToken moduleToken = cu.getClassByName("module").get().getName().getTokenRange().get().getBegin();
+        assertEquals(IDENTIFIER, moduleToken.getKind());
+    }
+
+    @Test
+    void issue988RequireTransitiveShouldRequireAModuleCalledTransitive() {
+        CompilationUnit cu = parse("module X { requires transitive; }");
+        ModuleRequiresDirective requiresTransitive = (ModuleRequiresDirective) cu.getModule().get().getDirectives().get(0);
+        assertEquals("transitive", requiresTransitive.getNameAsString());
+        assertEquals(IDENTIFIER, requiresTransitive.getName().getTokenRange().get().getBegin().getKind());
+    }
+
+    @Test
+    void jlsExample1() {
+        CompilationUnit cu = parse(
+                "@Foo(1) @Foo(2) @Bar " +
+                        "module M.N {" +
+                        "  requires A.B;" +
+                        "  requires transitive C.D;" +
+                        "  requires static E.F;" +
+                        "  requires transitive static G.H;" +
+                        "" +
+                        "  exports P.Q;" +
+                        "  exports R.S to T1.U1, T2.U2;" +
+                        "" +
+                        "  opens P.Q;" +
+                        "  opens R.S to T1.U1, T2.U2;" +
+                        "" +
+                        "  uses V.W;" +
+                        "  provides X.Y with Z1.Z2, Z3.Z4;" +
+                        "}");
+
+        ModuleDeclaration module = cu.getModule().get();
+        assertEquals("M.N", module.getNameAsString());
+        assertFalse(module.isOpen());
+        assertThat(module.getAnnotations()).containsExactly(
+                new SingleMemberAnnotationExpr(new Name("Foo"), new IntegerLiteralExpr("1")),
+                new SingleMemberAnnotationExpr(new Name("Foo"), new IntegerLiteralExpr("2")),
+                new MarkerAnnotationExpr(new Name("Bar")));
+
+        ModuleRequiresDirective moduleRequiresStmt = module.getDirectives().get(0).asModuleRequiresStmt();
+        assertThat(moduleRequiresStmt.getNameAsString()).isEqualTo("A.B");
+        assertThat(moduleRequiresStmt.getModifiers()).isEmpty();
+
+        ModuleExportsDirective moduleExportsStmt = module.getDirectives().get(5).asModuleExportsStmt();
+        assertThat(moduleExportsStmt.getNameAsString()).isEqualTo("R.S");
+        assertThat(moduleExportsStmt.getModuleNames()).containsExactly(parseName("T1.U1"), parseName("T2.U2"));
+
+        ModuleOpensDirective moduleOpensStmt = module.getDirectives().get(7).asModuleOpensStmt();
+        assertThat(moduleOpensStmt.getNameAsString()).isEqualTo("R.S");
+        assertThat(moduleOpensStmt.getModuleNames()).containsExactly(parseName("T1.U1"), parseName("T2.U2"));
+
+        ModuleUsesDirective moduleUsesStmt = module.getDirectives().get(8).asModuleUsesStmt();
+        assertThat(moduleUsesStmt.getNameAsString()).isEqualTo("V.W");
+
+        ModuleProvidesDirective moduleProvidesStmt = module.getDirectives().get(9).asModuleProvidesStmt();
+        assertThat(moduleProvidesStmt.getNameAsString()).isEqualTo("X.Y");
+        assertThat(moduleProvidesStmt.getWith()).containsExactly(
+                parseName("Z1.Z2"),
+                parseName("Z3.Z4"));
+
+    }
+
+    @Test
+    void jlsExample2HasAnOpenModule() {
+        CompilationUnit cu = parse("open module M.N {}");
+
+        ModuleDeclaration module = cu.getModule().get();
+        assertEquals("M.N", module.getNameAsString());
+        assertTrue(module.isOpen());
+    }
+
+    @Test
+    void testPrettyPrinting() {
+        CompilationUnit cu = parse(
+                "@Foo(1) @Foo(2) @Bar " +
+                        "module M.N {" +
+                        "  requires A.B;" +
+                        "  requires transitive C.D;" +
+                        "  requires static E.F;" +
+                        "  requires static transitive G.H;" +
+                        "" +
+                        "  exports P.Q;" +
+                        "  exports R.S to T1.U1, T2.U2;" +
+                        "" +
+                        "  opens P.Q;" +
+                        "  opens R.S to T1.U1, T2.U2;" +
+                        "" +
+                        "  uses V.W;" +
+                        "  provides X.Y with Z1.Z2, Z3.Z4;" +
+                        "}");
+
+        assertEquals(
+                "@Foo(1)" + EOL +
+                        "@Foo(2)" + EOL +
+                        "@Bar" + EOL +
+                        "module M.N {" + EOL +
+                        "    requires A.B;" + EOL +
+                        "    requires transitive C.D;" + EOL +
+                        "    requires static E.F;" + EOL +
+                        "    requires static transitive G.H;" + EOL +
+                        "    exports P.Q;" + EOL +
+                        "    exports R.S to T1.U1, T2.U2;" + EOL +
+                        "    opens P.Q;" + EOL +
+                        "    opens R.S to T1.U1, T2.U2;" + EOL +
+                        "    uses V.W;" + EOL +
+                        "    provides X.Y with Z1.Z2, Z3.Z4;" + EOL +
+                        "}" + EOL, cu.toString());
+
+    }
+
+    @Test
+    void testCsmPrinting() {
+        CompilationUnit cu = parse(
+                "@Foo(1) @Foo(2) @Bar " +
+                        "open module M.N {" +
+                        "  requires A.B;" +
+                        "  requires transitive C.D;" +
+                        "  requires static E.F;" +
+                        "  requires transitive static G.H;" +
+                        "" +
+                        "  exports P.Q;" +
+                        "  exports R.S to T1.U1, T2.U2;" +
+                        "" +
+                        "  opens P.Q;" +
+                        "  opens R.S to T1.U1, T2.U2;" +
+                        "" +
+                        "  uses V.W;" +
+                        "  provides X.Y with Z1.Z2, Z3.Z4;" +
+                        "}");
+
+        assertEquals(
+                "@Foo(1)" + EOL +
+                        "@Foo(2)" + EOL +
+                        "@Bar" + EOL +
+                        "open module M.N {" + EOL +
+                        "    requires A.B;" + EOL +
+                        "    requires transitive C.D;" + EOL +
+                        "    requires static E.F;" + EOL +
+                        "    requires transitive static G.H;" + EOL +
+                        "    exports P.Q;" + EOL +
+                        "    exports R.S to T1.U1, T2.U2;" + EOL +
+                        "    opens P.Q;" + EOL +
+                        "    opens R.S to T1.U1, T2.U2;" + EOL +
+                        "    uses V.W;" + EOL +
+                        "    provides X.Y with Z1.Z2, Z3.Z4;" + EOL +
+                        "}" + EOL, ConcreteSyntaxModel.genericPrettyPrint(cu));
+
+    }
+
+    @Test
+    void fluentInterface() {
+        ModuleDeclaration moduleDeclaration = new CompilationUnit()
+                .setModule("com.laamella.base")
+                .addSingleMemberAnnotation(SuppressWarnings.class, "\"module\"")
+                .addDirective("requires transitive java.desktop;")
+                .addDirective("exports com.laamella.base.entity.channel;")
+                .addDirective("exports com.laamella.base.entity.channel.internal to com.laamella.core;")
+                .addDirective("uses com.laamella.base.util.internal.FactoryDelegate;");
+
+        moduleDeclaration.getDirectives()
+                .addLast(new ModuleExportsDirective()
+                        .setName("foo.bar")
+                        .addModuleName("other.foo")
+                        .addModuleName("other.bar")
+                );
+
+        moduleDeclaration
+                .addDirective(new ModuleExportsDirective()
+                        .setName("foo.bar.x")
+                        .addModuleName("other.foo")
+                        .addModuleName("other.bar")
+                );
+
+        assertEqualsNoEol("@SuppressWarnings(\"module\")\n" +
+                "module com.laamella.base {\n" +
+                "    requires transitive java.desktop;\n" +
+                "    exports com.laamella.base.entity.channel;\n" +
+                "    exports com.laamella.base.entity.channel.internal to com.laamella.core;\n" +
+                "    uses com.laamella.base.util.internal.FactoryDelegate;\n" +
+                "    exports foo.bar to other.foo, other.bar;\n" +
+                "    exports foo.bar.x to other.foo, other.bar;\n" +
+                "}\n", moduleDeclaration.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelAcceptanceTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelAcceptanceTest.java
new file mode 100644
index 0000000..6567a81
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelAcceptanceTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.printer;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.utils.CodeGenerationUtils;
+import com.github.javaparser.utils.TestUtils;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ConcreteSyntaxModelAcceptanceTest {
+    private final Path rootDir = CodeGenerationUtils.mavenModuleRoot(ConcreteSyntaxModelAcceptanceTest.class).resolve("src/test/test_sourcecode");
+
+    private String prettyPrint(Node node) {
+        return ConcreteSyntaxModel.genericPrettyPrint(node);
+    }
+
+    private String prettyPrintedExpectation(String name) throws IOException {
+        return TestUtils.readResource("com/github/javaparser/printer/" + name + "_prettyprinted");
+    }
+
+    @Test
+    void printingExamplePrettyPrintVisitor() throws IOException {
+        CompilationUnit cu = parse(rootDir.resolve("com/github/javaparser/printer/PrettyPrintVisitor.java"));
+        assertEquals(prettyPrintedExpectation("PrettyPrintVisitor"), prettyPrint(cu));
+    }
+
+    @Test
+    void printingExampleJavaConcepts() throws IOException {
+        CompilationUnit cu = parse(rootDir.resolve("com/github/javaparser/printer/JavaConcepts.java"));
+        assertEquals(prettyPrintedExpectation("JavaConcepts"), prettyPrint(cu));
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelTest.java
new file mode 100644
index 0000000..c9c0fb8
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.
+ *
+ * This file is part of 
+ *
+ * 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.printer;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.ClassExpr;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ConcreteSyntaxModelTest {
+
+    private String print(Node node) {
+        return ConcreteSyntaxModel.genericPrettyPrint(node);
+    }
+
+    @Test
+    void printSimpleClassExpr() {
+        ClassExpr expr = parseExpression("Foo.class");
+        assertEquals("Foo.class", print(expr));
+    }
+
+    @Test
+    void printArrayClassExpr() {
+        ClassExpr expr = parseExpression("Foo[].class");
+        assertEquals("Foo[].class", print(expr));
+    }
+
+    @Test
+    void printGenericClassExpr() {
+        ClassExpr expr = parseExpression("Foo<String>.class");
+        assertEquals("Foo<String>.class", print(expr));
+    }
+
+    @Test
+    void printSimplestClass() {
+        Node node = parse("class A {}");
+        assertEquals("class A {" + EOL +
+                "}" + EOL, print(node));
+    }
+
+    @Test
+    void printAClassWithField() {
+        Node node = parse("class A { int a; }");
+        assertEquals("class A {" + EOL
+                + EOL +
+                "    int a;" + EOL +
+                "}" + EOL, print(node));
+    }
+
+    @Test
+    void printParameters() {
+        Node node = parseBodyDeclaration("int x(int y, int z) {}");
+        assertEquals("int x(int y, int z) {" + EOL + "}", print(node));
+    }
+
+    @Test
+    void printReceiverParameter() {
+        Node node = parseBodyDeclaration("int x(X A.B.this, int y, int z) {}");
+        assertEquals("int x(X A.B.this, int y, int z) {" + EOL + "}", print(node));
+    }
+
+    @Test
+    void printAnEmptyInterface() {
+        Node node = parse("interface A {}");
+        assertEquals("interface A {" + EOL +
+                "}" + EOL, print(node));
+    }
+
+    @Test
+    void printAnEmptyInterfaceWithModifier() {
+        Node node = parse("public interface A {}");
+        assertEquals("public interface A {" + EOL +
+                "}" + EOL, print(node));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/DotPrinterTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/DotPrinterTest.java
new file mode 100644
index 0000000..d168969
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/DotPrinterTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.printer;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.Expression;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class DotPrinterTest {
+    @Test
+    void testWithType() {
+        String expectedOutput = "digraph {" + System.lineSeparator();
+        expectedOutput += "n0 [label=\"root (MethodCallExpr)\"];" + System.lineSeparator();
+        expectedOutput += "n1 [label=\"name (SimpleName)\"];" + System.lineSeparator();
+        expectedOutput += "n0 -> n1;" + System.lineSeparator();
+        expectedOutput += "n2 [label=\"identifier='x'\"];" + System.lineSeparator();
+        expectedOutput += "n1 -> n2;" + System.lineSeparator();
+        expectedOutput += "n3 [label=\"arguments\"];" + System.lineSeparator();
+        expectedOutput += "n0 -> n3;" + System.lineSeparator();
+        expectedOutput += "n4 [label=\"argument (IntegerLiteralExpr)\"];" + System.lineSeparator();
+        expectedOutput += "n3 -> n4;" + System.lineSeparator();
+        expectedOutput += "n5 [label=\"value='1'\"];" + System.lineSeparator();
+        expectedOutput += "n4 -> n5;" + System.lineSeparator();
+        expectedOutput += "n6 [label=\"argument (IntegerLiteralExpr)\"];" + System.lineSeparator();
+        expectedOutput += "n3 -> n6;" + System.lineSeparator();
+        expectedOutput += "n7 [label=\"value='1'\"];" + System.lineSeparator();
+        expectedOutput += "n6 -> n7;" + System.lineSeparator();
+        expectedOutput += "}";
+
+        DotPrinter dotPrinter = new DotPrinter(true);
+        Expression expression = parseExpression("x(1,1)");
+        String output = dotPrinter.output(expression);
+        assertEquals(expectedOutput, output);
+    }
+
+    @Test
+    void testWithoutType() {
+        String expectedOutput = "digraph {" + System.lineSeparator();
+        expectedOutput += "n0 [label=\"root\"];" + System.lineSeparator();
+        expectedOutput += "n1 [label=\"operator='PLUS'\"];" + System.lineSeparator();
+        expectedOutput += "n0 -> n1;" + System.lineSeparator();
+        expectedOutput += "n2 [label=\"left\"];" + System.lineSeparator();
+        expectedOutput += "n0 -> n2;" + System.lineSeparator();
+        expectedOutput += "n3 [label=\"value='1'\"];" + System.lineSeparator();
+        expectedOutput += "n2 -> n3;" + System.lineSeparator();
+        expectedOutput += "n4 [label=\"right\"];" + System.lineSeparator();
+        expectedOutput += "n0 -> n4;" + System.lineSeparator();
+        expectedOutput += "n5 [label=\"value='1'\"];" + System.lineSeparator();
+        expectedOutput += "n4 -> n5;" + System.lineSeparator();
+        expectedOutput += "}";
+
+        DotPrinter dotPrinter = new DotPrinter(false);
+        Expression expression = parseExpression("1+1");
+        String output = dotPrinter.output(expression);
+        assertEquals(expectedOutput, output);
+    }
+
+    @Test
+    void testIssue1871() {
+        DotPrinter printer = new DotPrinter(false);
+        CompilationUnit cu = parse("//q\"q\nclass X{}");
+        String output = printer.output(cu);
+        assertEqualsNoEol("digraph {\n" +
+                "n0 [label=\"root\"];\n" +
+                "n1 [label=\"types\"];\n" +
+                "n0 -> n1;\n" +
+                "n2 [label=\"type\"];\n" +
+                "n1 -> n2;\n" +
+                "n3 [label=\"isInterface='false'\"];\n" +
+                "n2 -> n3;\n" +
+                "n4 [label=\"name\"];\n" +
+                "n2 -> n4;\n" +
+                "n5 [label=\"identifier='X'\"];\n" +
+                "n4 -> n5;\n" +
+                "n6 [label=\"comment\"];\n" +
+                "n2 -> n6;\n" +
+                "n7 [label=\"content='q\\\"q'\"];\n" +
+                "n6 -> n7;\n" +
+                "}", output);
+    }
+}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/storage/B.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/JsonPrinterTest.java
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/storage/B.java
copy to javaparser-core-testing/src/test/java/com/github/javaparser/printer/JsonPrinterTest.java
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java
new file mode 100644
index 0000000..f59583c
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.
+ *
+ * This file is part of 
+ *
+ * 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.printer;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.comments.LineComment;
+import com.github.javaparser.ast.expr.CastExpr;
+import com.github.javaparser.ast.expr.ClassExpr;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.type.Type;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class PrettyPrintVisitorTest {
+
+    @Test
+    void getMaximumCommonTypeWithoutAnnotations() {
+        VariableDeclarationExpr vde1 = parseVariableDeclarationExpr("int a[], b[]");
+        assertEquals("int[]", vde1.getMaximumCommonType().get().toString());
+
+        VariableDeclarationExpr vde2 = parseVariableDeclarationExpr("int[][] a[], b[]");
+        assertEquals("int[][][]", vde2.getMaximumCommonType().get().toString());
+
+        VariableDeclarationExpr vde3 = parseVariableDeclarationExpr("int[][] a, b[]");
+        assertEquals("int[][]", vde3.getMaximumCommonType().get().toString());
+    }
+
+    @Test
+    void getMaximumCommonTypeWithAnnotations() {
+        VariableDeclarationExpr vde1 = parseVariableDeclarationExpr("int a @Foo [], b[]");
+        assertEquals("int", vde1.getMaximumCommonType().get().toString());
+
+        VariableDeclarationExpr vde2 = parseVariableDeclarationExpr("int[]@Foo [] a[], b[]");
+        assertEquals("int[] @Foo [][]", vde2.getMaximumCommonType().get().toString());
+    }
+
+    private String print(Node node) {
+        return new PrettyPrinter().print(node);
+    }
+
+    @Test
+    void printSimpleClassExpr() {
+        ClassExpr expr = parseExpression("Foo.class");
+        assertEquals("Foo.class", print(expr));
+    }
+
+    @Test
+    void printArrayClassExpr() {
+        ClassExpr expr = parseExpression("Foo[].class");
+        assertEquals("Foo[].class", print(expr));
+    }
+
+    @Test
+    void printGenericClassExpr() {
+        ClassExpr expr = parseExpression("Foo<String>.class");
+        assertEquals("Foo<String>.class", print(expr));
+    }
+
+    @Test
+    void printSimplestClass() {
+        Node node = parse("class A {}");
+        assertEquals("class A {" + EOL +
+                "}" + EOL, print(node));
+    }
+
+    @Test
+    void printAClassWithField() {
+        Node node = parse("class A { int a; }");
+        assertEquals("class A {" + EOL
+                + EOL +
+                "    int a;" + EOL +
+                "}" + EOL, print(node));
+    }
+
+    @Test
+    void printAReceiverParameter() {
+        Node node = parseBodyDeclaration("int x(@O X A.B.this, int y) { }");
+        assertEquals("int x(@O X A.B.this, int y) {" + EOL + "}", print(node));
+    }
+
+    @Test
+    void printLambdaIntersectionTypeAssignment() {
+        String code = "class A {" + EOL +
+                "  void f() {" + EOL +
+                "    Runnable r = (Runnable & Serializable) (() -> {});" + EOL +
+                "    r = (Runnable & Serializable)() -> {};" + EOL +
+                "    r = (Runnable & I)() -> {};" + EOL +
+                "  }}";
+        CompilationUnit cu = parse(code);
+        MethodDeclaration methodDeclaration = (MethodDeclaration) cu.getType(0).getMember(0);
+
+        assertEquals("Runnable r = (Runnable & Serializable) (() -> {" + EOL + "});", print(methodDeclaration.getBody().get().getStatements().get(0)));
+    }
+
+    @Test
+    void printIntersectionType() {
+        String code = "(Runnable & Serializable) (() -> {})";
+        Expression expression = parseExpression(code);
+        Type type = ((CastExpr) expression).getType();
+
+        assertEquals("Runnable & Serializable", print(type));
+    }
+
+    @Test
+    void printLambdaIntersectionTypeReturn() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        CompilationUnit cu = parse(code);
+        MethodDeclaration methodDeclaration = (MethodDeclaration) cu.getType(0).getMember(0);
+
+        assertEquals("return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getKey().compareTo(c2.getKey());", print(methodDeclaration.getBody().get().getStatements().get(0)));
+    }
+
+    @Test
+    void printClassWithoutJavaDocButWithComment() {
+        String code = String.format("/** javadoc */ public class A { %s// stuff%s}", EOL, EOL);
+        CompilationUnit cu = parse(code);
+        PrettyPrinterConfiguration ignoreJavaDoc = new PrettyPrinterConfiguration().setPrintJavadoc(false);
+        String content = cu.toString(ignoreJavaDoc);
+        assertEquals(String.format("public class A {%s    // stuff%s}%s", EOL, EOL, EOL), content);
+    }
+
+    @Test
+    void printImportsDefaultOrder() {
+        String code = "import x.y.z;import a.b.c;import static b.c.d;class c {}";
+        CompilationUnit cu = parse(code);
+        String content = cu.toString();
+        assertEqualsNoEol("import x.y.z;\n" +
+                "import a.b.c;\n" +
+                "import static b.c.d;\n" +
+                "\n" +
+                "class c {\n" +
+                "}\n", content);
+    }
+
+    @Test
+    void printImportsOrdered() {
+        String code = "import x.y.z;import a.b.c;import static b.c.d;class c {}";
+        CompilationUnit cu = parse(code);
+        PrettyPrinterConfiguration orderImports = new PrettyPrinterConfiguration().setOrderImports(true);
+        String content = cu.toString(orderImports);
+        assertEqualsNoEol("import static b.c.d;\n" +
+                "import a.b.c;\n" +
+                "import x.y.z;\n" +
+                "\n" +
+                "class c {\n" +
+                "}\n", content);
+    }
+
+    @Test
+    void multilineJavadocGetsFormatted() {
+        CompilationUnit cu = new CompilationUnit();
+        cu.addClass("X").addMethod("abc").setJavadocComment("line1\n   line2 *\n * line3");
+
+        assertEqualsNoEol("public class X {\n" +
+                "\n" +
+                "    /**\n" +
+                "     * line1\n" +
+                "     *    line2 *\n" +
+                "     *  line3\n" +
+                "     */\n" +
+                "    void abc() {\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void emptyJavadocGetsFormatted() {
+        CompilationUnit cu = new CompilationUnit();
+        cu.addClass("X").addMethod("abc").setJavadocComment("");
+
+        assertEqualsNoEol("public class X {\n" +
+                "\n" +
+                "    /**\n" +
+                "     */\n" +
+                "    void abc() {\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void multilineJavadocWithLotsOfEmptyLinesGetsFormattedNeatly() {
+        CompilationUnit cu = new CompilationUnit();
+        cu.addClass("X").addMethod("abc").setJavadocComment("\n\n\n ab\n\n\n cd\n\n\n");
+
+        assertEqualsNoEol("public class X {\n" +
+                "\n" +
+                "    /**\n" +
+                "     * ab\n" +
+                "     *\n" +
+                "     * cd\n" +
+                "     */\n" +
+                "    void abc() {\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void singlelineJavadocGetsFormatted() {
+        CompilationUnit cu = new CompilationUnit();
+        cu.addClass("X").addMethod("abc").setJavadocComment("line1");
+
+        assertEqualsNoEol("public class X {\n" +
+                "\n" +
+                "    /**\n" +
+                "     * line1\n" +
+                "     */\n" +
+                "    void abc() {\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void javadocAlwaysGetsASpaceBetweenTheAsteriskAndTheRestOfTheLine() {
+        CompilationUnit cu = new CompilationUnit();
+        cu.addClass("X").addMethod("abc").setJavadocComment("line1\nline2");
+
+        assertEqualsNoEol("public class X {\n" +
+                "\n" +
+                "    /**\n" +
+                "     * line1\n" +
+                "     * line2\n" +
+                "     */\n" +
+                "    void abc() {\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void javadocAlwaysGetsAnAdditionalSpaceOrNeverGetsIt() {
+        CompilationUnit cu = new CompilationUnit();
+        cu.addClass("X").addMethod("abc").setJavadocComment("line1\n" +
+                "line2\n" +
+                "    3");
+
+        assertEqualsNoEol("public class X {\n" +
+                "\n" +
+                "    /**\n" +
+                "     * line1\n" +
+                "     * line2\n" +
+                "     *     3\n" +
+                "     */\n" +
+                "    void abc() {\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void singlelineCommentGetsFormatted() {
+        CompilationUnit cu = new CompilationUnit();
+        cu.addClass("X").addMethod("abc").setComment(new LineComment("   line1  \n "));
+
+        assertEqualsNoEol("public class X {\n" +
+                "\n" +
+                "    // line1\n" +
+                "    void abc() {\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    @Test
+    void blockcommentGetsNoFormatting() {
+        CompilationUnit cu = parse("class A {\n" +
+                "    public void helloWorld(String greeting, String name) {\n" +
+                "        //sdfsdfsdf\n" +
+                "            //sdfds\n" +
+                "        /*\n" +
+                "                            dgfdgfdgfdgfdgfd\n" +
+                "         */\n" +
+                "    }\n" +
+                "}\n");
+
+        assertEqualsNoEol("class A {\n" +
+                "\n" +
+                "    public void helloWorld(String greeting, String name) {\n" +
+                "    // sdfsdfsdf\n" +
+                "    // sdfds\n" +
+                "    /*\n" +
+                "                            dgfdgfdgfdgfdgfd\n" +
+                "         */\n" +
+                "    }\n" +
+                "}\n", cu.toString());
+    }
+
+    private String expected = "public class SomeClass {\n" +
+            "\n" +
+            "    /**\n" +
+            "     * tester line\n" +
+            "     * multi line comment\n" +
+            "     *   multi line comment\n" +
+            "     * multi line comment\n" +
+            "     *    multi line comment\n" +
+            "     */\n" +
+            "    public void add(int x, int y) {\n" +
+            "    }\n" +
+            "}\n";
+
+    @Test
+    void javadocIssue1907_allLeadingSpaces() {
+        String input_allLeadingSpaces = "public class SomeClass{" +
+                "/**\n" +
+                " * tester line\n" +
+                " * multi line comment\n" +
+                " *   multi line comment\n" +
+                "   * multi line comment\n" +
+                "    multi line comment\n" +
+                " */\n" +
+                "public void add(int x, int y){}}";
+
+        CompilationUnit cu_allLeadingSpaces = parse(input_allLeadingSpaces);
+        assertEqualsNoEol(expected, cu_allLeadingSpaces.toString());
+    }
+
+    @Test
+    void javadocIssue1907_singleMissingLeadingSpace() {
+        String input_singleMissingLeadingSpace = "public class SomeClass{" +
+                "/**\n" +
+                "* tester line\n" +
+                " * multi line comment\n" +
+                " *   multi line comment\n" +
+                "   * multi line comment\n" +
+                "    multi line comment\n" +
+                " */\n" +
+                "public void add(int x, int y){}}";
+
+        CompilationUnit cu_singleMissingLeadingSpace = parse(input_singleMissingLeadingSpace);
+        assertEqualsNoEol(expected, cu_singleMissingLeadingSpace.toString());
+    }
+
+    @Test
+    void javadocIssue1907_leadingTab() {
+        String input_leadingTab = "public class SomeClass{" +
+                "/**\n" +
+                "\t * tester line\n" +
+                " * multi line comment\n" +
+                " *   multi line comment\n" +
+                "   * multi line comment\n" +
+                "    multi line comment\n" +
+                " */\n" +
+                "public void add(int x, int y){}}";
+
+        CompilationUnit cu_leadingTab = parse(input_leadingTab);
+        assertEqualsNoEol(expected, cu_leadingTab.toString());
+
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrinterTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrinterTest.java
new file mode 100644
index 0000000..912f0d1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/PrettyPrinterTest.java
@@ -0,0 +1,474 @@
+/*
+ * 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.printer;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseProblemException;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.PrimitiveType;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_9;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.StaticJavaParser.*;
+import static com.github.javaparser.printer.PrettyPrinterConfiguration.IndentType.TABS;
+import static com.github.javaparser.printer.PrettyPrinterConfiguration.IndentType.TABS_WITH_SPACE_ALIGN;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class PrettyPrinterTest {
+
+    private String prettyPrintField(String code) {
+        CompilationUnit cu = parse(code);
+        return new PrettyPrinter().print(cu.findFirst(FieldDeclaration.class).get());
+    }
+
+    private String prettyPrintVar(String code) {
+        CompilationUnit cu = parse(code);
+        return new PrettyPrinter().print(cu.findAll(VariableDeclarationExpr.class).get(0));
+    }
+
+    @Test
+    void printingArrayFields() {
+        String code;
+        code = "class A { int a, b[]; }";
+        assertEquals("int a, b[];", prettyPrintField(code));
+
+        code = "class A { int[] a[], b[]; }";
+        assertEquals("int[][] a, b;", prettyPrintField(code));
+
+        code = "class A { int[] a[][], b; }";
+        assertEquals("int[] a[][], b;", prettyPrintField(code));
+
+        code = "class A { int[] a, b; }";
+        assertEquals("int[] a, b;", prettyPrintField(code));
+
+        code = "class A { int a[], b[]; }";
+        assertEquals("int[] a, b;", prettyPrintField(code));
+    }
+
+    @Test
+    void printingArrayVariables() {
+        String code;
+        code = "class A { void foo(){ int a, b[]; }}";
+        assertEquals("int a, b[]", prettyPrintVar(code));
+
+        code = "class A { void foo(){ int[] a[], b[]; }}";
+        assertEquals("int[][] a, b", prettyPrintVar(code));
+
+        code = "class A { void foo(){ int[] a[][], b; }}";
+        assertEquals("int[] a[][], b", prettyPrintVar(code));
+
+        code = "class A { void foo(){ int[] a, b; }}";
+        assertEquals("int[] a, b", prettyPrintVar(code));
+
+        code = "class A { void foo(){ int a[], b[]; }}";
+        assertEquals("int[] a, b", prettyPrintVar(code));
+    }
+
+    private String prettyPrintConfigurable(String code) {
+        CompilationUnit cu = parse(code);
+        PrettyPrinter printer = new PrettyPrinter(new PrettyPrinterConfiguration().setVisitorFactory(TestVisitor::new));
+        return printer.print(cu.findFirst(ClassOrInterfaceDeclaration.class).get());
+    }
+
+    @Test
+    void printUseTestVisitor() {
+        String code;
+        code = "class A { void foo(){ int a, b[]; }}";
+        assertEquals("test", prettyPrintConfigurable(code));
+    }
+
+    @Test
+    void prettyColumnAlignParameters_enabled() {
+        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration()
+                .setColumnAlignParameters(true);
+
+        final String EOL = config.getEndOfLineCharacter();
+
+        String code = "class Example { void foo(Object arg0,Object arg1){ myMethod(1, 2, 3, 5, Object.class); } }";
+        String expected = "class Example {" + EOL +
+                "" + EOL +
+                "    void foo(Object arg0, Object arg1) {" + EOL +
+                "        myMethod(1," + EOL +
+                "                 2," + EOL +
+                "                 3," + EOL +
+                "                 5," + EOL +
+                "                 Object.class);" + EOL +
+                "    }" + EOL +
+                "}" + EOL +
+                "";
+
+        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
+    }
+
+    @Test
+    void prettyColumnAlignParameters_disabled() {
+        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration();
+        final String EOL = config.getEndOfLineCharacter();
+
+        String code = "class Example { void foo(Object arg0,Object arg1){ myMethod(1, 2, 3, 5, Object.class); } }";
+        String expected = "class Example {" + EOL +
+                "" + EOL +
+                "    void foo(Object arg0, Object arg1) {" + EOL +
+                "        myMethod(1, 2, 3, 5, Object.class);" + EOL +
+                "    }" + EOL +
+                "}" + EOL +
+                "";
+
+        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
+    }
+
+    @Test
+    void prettyAlignMethodCallChains_enabled() {
+        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration()
+                .setColumnAlignFirstMethodChain(true);
+
+        final String EOL = config.getEndOfLineCharacter();
+
+        String code = "class Example { void foo() { IntStream.range(0, 10).filter(x -> x % 2 == 0).map(x -> x * IntStream.of(1,3,5,1).sum()).forEach(System.out::println); } }";
+        String expected = "class Example {" + EOL +
+                "" + EOL +
+                "    void foo() {" + EOL +
+                "        IntStream.range(0, 10)" + EOL +
+                "                 .filter(x -> x % 2 == 0)" + EOL +
+                "                 .map(x -> x * IntStream.of(1, 3, 5, 1)" + EOL +
+                "                                        .sum())" + EOL +
+                "                 .forEach(System.out::println);" + EOL +
+                "    }" + EOL +
+                "}" + EOL +
+                "";
+
+        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
+    }
+
+    @Test
+    void prettyAlignMethodCallChains_disabled() {
+        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration();
+        final String EOL = config.getEndOfLineCharacter();
+
+        String code = "class Example { void foo() { IntStream.range(0, 10).filter(x -> x % 2 == 0).map(x -> x * IntStream.of(1,3,5,1).sum()).forEach(System.out::println); } }";
+        String expected = "class Example {" + EOL +
+                "" + EOL +
+                "    void foo() {" + EOL +
+                "        IntStream.range(0, 10).filter(x -> x % 2 == 0).map(x -> x * IntStream.of(1, 3, 5, 1).sum()).forEach(System.out::println);" + EOL +
+                "    }" + EOL +
+                "}" + EOL +
+                "";
+
+        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
+    }
+
+    @Test
+    void enumConstantsHorizontally() {
+        CompilationUnit cu = parse("enum X{A, B, C, D, E}");
+        assertEqualsNoEol("enum X {\n\n    A, B, C, D, E\n}\n", new PrettyPrinter().print(cu));
+    }
+
+    @Test
+    void enumConstantsVertically() {
+        CompilationUnit cu = parse("enum X{A, B, C, D, E, F}");
+        assertEqualsNoEol("enum X {\n\n    A,\n    B,\n    C,\n    D,\n    E,\n    F\n}\n", new PrettyPrinter().print(cu));
+    }
+
+    @Test
+    void printingInconsistentVariables() {
+        FieldDeclaration fieldDeclaration = parseBodyDeclaration("int a, b;").asFieldDeclaration();
+
+        assertEquals("int a, b;", fieldDeclaration.toString());
+
+        fieldDeclaration.getVariable(0).setType(PrimitiveType.doubleType());
+
+        assertEquals("??? a, b;", fieldDeclaration.toString());
+
+        fieldDeclaration.getVariable(1).setType(PrimitiveType.doubleType());
+
+        assertEquals("double a, b;", fieldDeclaration.toString());
+    }
+
+    @Test
+    void prettyAlignMethodCallChainsIndentsArgumentsWithBlocksCorrectly() {
+
+        CompilationUnit cu = parse("class Foo { void bar() { a.b.c.d.e; a.b.c().d().e(); a.b.c().d.e(); foo().bar().baz(boo().baa().bee()).bam(); foo().bar().baz(boo().baa().bee()).bam; foo().bar(Long.foo().b.bar(), bam).baz(); foo().bar().baz(foo, () -> { boo().baa().bee(); }).baz(() -> { boo().baa().bee(); }).bam(() -> { boo().baa().bee(); }); } }");
+        String printed = new PrettyPrinter(new PrettyPrinterConfiguration().setColumnAlignFirstMethodChain(true).setColumnAlignParameters(true).setIndentSize(1).setIndentType(TABS_WITH_SPACE_ALIGN))
+                .print(cu);
+
+        assertEqualsNoEol("class Foo {\n" +
+                "\n" +
+                "\tvoid bar() {\n" +
+                "\t\ta.b.c.d.e;\n" +
+                "\t\ta.b.c()\n" +
+                "\t\t   .d()\n" +
+                "\t\t   .e();\n" +
+                "\t\ta.b.c().d\n" +
+                "\t\t   .e();\n" +
+                "\t\tfoo().bar()\n" +
+                "\t\t     .baz(boo().baa().bee())\n" +
+                "\t\t     .bam();\n" +
+                "\t\tfoo().bar()\n" +
+                "\t\t     .baz(boo().baa().bee()).bam;\n" +
+                "\t\tfoo().bar(Long.foo().b.bar(),\n" +
+                "\t\t          bam)\n" +
+                "\t\t     .baz();\n" +
+                "\t\tfoo().bar()\n" +
+                "\t\t     .baz(foo,\n" +
+                "\t\t          () -> {\n" +
+                "\t\t          \tboo().baa()\n" +
+                "\t\t          \t     .bee();\n" +
+                "\t\t          })\n" +
+                "\t\t     .baz(() -> {\n" +
+                "\t\t     \tboo().baa()\n" +
+                "\t\t     \t     .bee();\n" +
+                "\t\t     })\n" +
+                "\t\t     .bam(() -> {\n" +
+                "\t\t     \tboo().baa()\n" +
+                "\t\t     \t     .bee();\n" +
+                "\t\t     });\n" +
+                "\t}\n" +
+                "}\n", printed);
+    }
+
+    @Test
+    void noChainsIndentsInIf() {
+        Statement cu = parseStatement("if (x.y().z()) { boo().baa().bee(); }");
+
+        String printed = new PrettyPrinter(new PrettyPrinterConfiguration().setColumnAlignFirstMethodChain(true))
+                .print(cu);
+
+        assertEqualsNoEol("if (x.y().z()) {\n" +
+                "    boo().baa()\n" +
+                "         .bee();\n" +
+                "}", printed);
+    }
+
+    @Test
+    void noChainsIndentsInFor() {
+        Statement cu = parseStatement("for(int x=1; x.y().z(); x.z().z()) { boo().baa().bee(); }");
+
+        String printed = new PrettyPrinter(new PrettyPrinterConfiguration().setColumnAlignFirstMethodChain(true))
+                .print(cu);
+
+        assertEqualsNoEol("for (int x = 1; x.y().z(); x.z().z()) {\n" +
+                "    boo().baa()\n" +
+                "         .bee();\n" +
+                "}", printed);
+    }
+
+    @Test
+    void noChainsIndentsInWhile() {
+        Statement cu = parseStatement("while(x.y().z()) { boo().baa().bee(); }");
+
+        String printed = new PrettyPrinter(new PrettyPrinterConfiguration().setColumnAlignFirstMethodChain(true))
+                .print(cu);
+
+        assertEqualsNoEol("while (x.y().z()) {\n" +
+                "    boo().baa()\n" +
+                "         .bee();\n" +
+                "}", printed);
+    }
+
+    @Test
+    void indentWithTabsAsFarAsPossible() {
+
+        CompilationUnit cu = parse("class Foo { void bar() { foo().bar().baz(() -> { boo().baa().bee(a, b, c); }).bam(); } }");
+        String printed = new PrettyPrinter(new PrettyPrinterConfiguration()
+                .setColumnAlignFirstMethodChain(true)
+                .setColumnAlignParameters(true)
+                .setIndentType(TABS)
+                .setIndentSize(1))
+                .print(cu);
+
+        assertEqualsNoEol("class Foo {\n" +
+                "\n" +
+                "\tvoid bar() {\n" +
+                "\t\tfoo().bar()\n" +
+                "\t\t\t .baz(() -> {\n" +
+                "\t\t\t\t boo().baa()\n" +
+                "\t\t\t\t\t  .bee(a,\n" +
+                "\t\t\t\t\t\t   b,\n" +
+                "\t\t\t\t\t\t   c);\n" +
+                "\t\t\t })\n" +
+                "\t\t\t .bam();\n" +
+                "\t}\n" +
+                "}\n", printed);
+    }
+
+    @Test
+    void indentWithTabsAlignWithSpaces() {
+
+        CompilationUnit cu = parse("class Foo { void bar() { foo().bar().baz(() -> { boo().baa().bee(a, b, c); }).baz(() -> { return boo().baa(); }).bam(); } }");
+        String printed = new PrettyPrinter(new PrettyPrinterConfiguration()
+                .setColumnAlignFirstMethodChain(true)
+                .setColumnAlignParameters(true)
+                .setIndentType(TABS_WITH_SPACE_ALIGN)
+                .setIndentSize(1))
+                .print(cu);
+
+        assertEqualsNoEol("class Foo {\n" +
+                "\n" +
+                "\tvoid bar() {\n" +
+                "\t\tfoo().bar()\n" +
+                "\t\t     .baz(() -> {\n" +
+                "\t\t     \tboo().baa()\n" +
+                "\t\t     \t     .bee(a,\n" +
+                "\t\t     \t          b,\n" +
+                "\t\t     \t          c);\n" +
+                "\t\t     })\n" +
+                "\t\t     .baz(() -> {\n" +
+                "\t\t     \treturn boo().baa();\n" +
+                "\t\t     })\n" +
+                "\t\t     .bam();\n" +
+                "\t}\n" +
+                "}\n", printed);
+    }
+
+    @Test
+    void printAnnotationsAtPrettyPlaces() {
+
+        JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
+        ParseResult<CompilationUnit> parseResult = javaParser.parse(COMPILATION_UNIT, provider("@Documented\n" +
+                "@Repeatable\n" +
+                "package com.github.javaparser;\n" +
+                "\n" +
+                "import java.lang.annotation.Documented;\n" +
+                "import java.lang.annotation.Repeatable;\n" +
+                "\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "@interface Annotation {\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    String value();\n" +
+                "}\n" +
+                "\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "class Class<@Documented @Repeatable T> {\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    byte b;\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    Class(@Documented @Repeatable int i) {\n" +
+                "        @Documented\n" +
+                "        @Repeatable\n" +
+                "        short s;\n" +
+                "    }\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    void method(@Documented @Repeatable Class this) {\n" +
+                "        for (@Deprecated int i : arr4[0]) {\n" +
+                "            x--;\n" +
+                "        }\n" +
+                "    }\n" +
+                "\n" +
+                "    void method(@Documented @Repeatable Class this, int i) {\n" +
+                "    }\n" +
+                "}\n" +
+                "\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "enum Foo {\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    BAR\n" +
+                "}\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "module foo.bar {\n" +
+                "}\n"));
+        if (!parseResult.isSuccessful()) {
+            throw new ParseProblemException(parseResult.getProblems());
+        }
+        CompilationUnit cu = parseResult.getResult().orElseThrow(AssertionError::new);
+        String printed = new PrettyPrinter().print(cu);
+
+        assertEqualsNoEol("@Documented\n" +
+                "@Repeatable\n" +
+                "package com.github.javaparser;\n" +
+                "\n" +
+                "import java.lang.annotation.Documented;\n" +
+                "import java.lang.annotation.Repeatable;\n" +
+                "\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "@interface Annotation {\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    String value();\n" +
+                "}\n" +
+                "\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "class Class<@Documented @Repeatable T> {\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    byte b;\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    Class(@Documented @Repeatable int i) {\n" +
+                "        @Documented\n" +
+                "        @Repeatable\n" +
+                "        short s;\n" +
+                "    }\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    void method(@Documented @Repeatable Class this) {\n" +
+                "        for (@Deprecated int i : arr4[0]) {\n" +
+                "            x--;\n" +
+                "        }\n" +
+                "    }\n" +
+                "\n" +
+                "    void method(@Documented @Repeatable Class this, int i) {\n" +
+                "    }\n" +
+                "}\n" +
+                "\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "enum Foo {\n" +
+                "\n" +
+                "    @Documented\n" +
+                "    @Repeatable\n" +
+                "    BAR\n" +
+                "}\n" +
+                "@Documented\n" +
+                "@Repeatable\n" +
+                "module foo.bar {\n" +
+                "}\n", printed);
+    }
+}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/TestVisitor.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/TestVisitor.java
similarity index 100%
rename from javaparser-testing/src/test/java/com/github/javaparser/printer/TestVisitor.java
rename to javaparser-core-testing/src/test/java/com/github/javaparser/printer/TestVisitor.java
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/XmlPrinterTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/XmlPrinterTest.java
new file mode 100644
index 0000000..437c42c
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/XmlPrinterTest.java
@@ -0,0 +1,41 @@
+package com.github.javaparser.printer;
+
+import com.github.javaparser.ast.expr.Expression;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class XmlPrinterTest {
+    @Test
+    void testWithType() {
+        Expression expression = parseExpression("1+1");
+        XmlPrinter xmlOutput = new XmlPrinter(true);
+
+        String output = xmlOutput.output(expression);
+
+        assertEquals("<root type='BinaryExpr' operator='PLUS'><left type='IntegerLiteralExpr' value='1'></left><right type='IntegerLiteralExpr' value='1'></right></root>", output);
+    }
+
+    @Test
+    void testWithoutType() {
+        Expression expression = parseExpression("1+1");
+
+        XmlPrinter xmlOutput = new XmlPrinter(false);
+
+        String output = xmlOutput.output(expression);
+
+        assertEquals("<root operator='PLUS'><left value='1'></left><right value='1'></right></root>", output);
+    }
+
+    @Test
+    void testList() {
+        Expression expression = parseExpression("a(1,2)");
+
+        XmlPrinter xmlOutput = new XmlPrinter(true);
+
+        String output = xmlOutput.output(expression);
+
+        assertEquals("<root type='MethodCallExpr'><name type='SimpleName' identifier='a'></name><arguments><argument type='IntegerLiteralExpr' value='1'></argument><argument type='IntegerLiteralExpr' value='2'></argument></arguments></root>", output);
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/YamlPrinterTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/YamlPrinterTest.java
new file mode 100644
index 0000000..544b6e3
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/YamlPrinterTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.
+ *
+ * This file is part of 
+ *
+ * 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.printer;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.Expression;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.TestUtils.readTextResource;
+
+class YamlPrinterTest {
+
+    private String read(String filename) {
+        return readTextResource(YamlPrinterTest.class, filename);
+    }
+
+    @Test
+    void testWithType() {
+        YamlPrinter yamlPrinter = new YamlPrinter(true);
+        Expression expression = parseExpression("x(1,1)");
+        String output = yamlPrinter.output(expression);
+        assertEqualsNoEol(read("yamlWithType.yaml"), output);
+    }
+
+    @Test
+    void testWithoutType() {
+        YamlPrinter yamlPrinter = new YamlPrinter(false);
+        Expression expression = parseExpression("1+1");
+        String output = yamlPrinter.output(expression);
+        assertEqualsNoEol(read("yamlWithoutType.yaml"), output);
+    }
+
+    @Test
+    void testWithColonFollowedBySpaceInValue() {
+        YamlPrinter yamlPrinter = new YamlPrinter(true);
+        Expression expression = parseExpression("\"a\\\\: b\"");
+        String output = yamlPrinter.output(expression);
+        assertEqualsNoEol(read("yamlWithColonFollowedBySpaceInValue.yaml"), output);
+    }
+
+    @Test
+    void testWithColonFollowedByLineSeparatorInValue() {
+        YamlPrinter yamlPrinter = new YamlPrinter(true);
+        Expression expression = parseExpression("\"a\\\\:\\\\nb\"");
+        String output = yamlPrinter.output(expression);
+        assertEqualsNoEol(read("yamlWithColonFollowedByLineSeparatorInValue.yaml"), output);
+    }
+
+    @Test
+    void testParsingJavadocWithQuoteAndNewline() {
+        String code = "/**\n" + 
+                " * \" this comment contains a quote and newlines\n" +
+                " */\n" + 
+                "public class Dog {}";
+
+        YamlPrinter yamlPrinter = new YamlPrinter(true);
+        CompilationUnit computationUnit = parse(code);
+        String output = yamlPrinter.output(computationUnit);
+        assertEqualsNoEol(read("yamlParsingJavadocWithQuoteAndNewline.yaml"), output);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/AbstractLexicalPreservingTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/AbstractLexicalPreservingTest.java
new file mode 100644
index 0000000..4312a02
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/AbstractLexicalPreservingTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.printer.lexicalpreservation;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.Expression;
+
+import java.io.IOException;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.utils.TestUtils.readResource;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public abstract class AbstractLexicalPreservingTest {
+
+    protected CompilationUnit cu;
+    protected Expression expression;
+
+    protected void considerCode(String code) {
+        cu = LexicalPreservingPrinter.setup(parse(code));
+    }
+
+    protected void considerExpression(String code) {
+        expression = LexicalPreservingPrinter.setup(parseExpression(code));
+    }
+
+    protected String considerExample(String resourceName) throws IOException {
+        String code = readExample(resourceName);
+        considerCode(code);
+        return code;
+    }
+
+    protected String readExample(String resourceName) throws IOException {
+        return readResource("com/github/javaparser/lexical_preservation_samples/" + resourceName + ".java.txt");
+    }
+
+    protected void assertTransformed(String exampleName, Node node) throws IOException {
+        String expectedCode = readExample(exampleName + "_expected");
+        String actualCode = LexicalPreservingPrinter.print(node);
+        assertEquals(expectedCode, actualCode);
+    }
+
+    protected void assertUnchanged(String exampleName) throws IOException {
+        String code = considerExample(exampleName + "_original");
+        assertEquals(code, LexicalPreservingPrinter.print(cu != null ? cu : expression));
+    }
+
+    protected void assertTransformedToString(String expectedPartialCode, Node node) {
+        String actualCode = LexicalPreservingPrinter.print(node);
+        assertEquals(expectedPartialCode, actualCode);
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculatorTest.java
new file mode 100644
index 0000000..45e8c73
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculatorTest.java
@@ -0,0 +1,431 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.GeneratedJavaParserConstants;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.comments.JavadocComment;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.ArrayType;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.printer.ConcreteSyntaxModel;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmIndent;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmUnindent;
+import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static com.github.javaparser.TokenTypes.eolTokenKind;
+import static com.github.javaparser.TokenTypes.spaceTokenKind;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static com.github.javaparser.printer.lexicalpreservation.DifferenceElement.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class DifferenceElementCalculatorTest extends AbstractLexicalPreservingTest {
+
+    @Test
+    void calculateDifferenceEmpty() {
+        LexicalDifferenceCalculator.CalculatedSyntaxModel a = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel b = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(a, b);
+        assertEquals(0, differenceElements.size());
+    }
+
+    @Test
+    void calculateDifferenceAIsEmpty() {
+        Node n1 = new FieldDeclaration();
+        Node n2 = new MethodDeclaration();
+
+        LexicalDifferenceCalculator.CalculatedSyntaxModel a = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel b = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Arrays.asList(
+                new CsmToken(GeneratedJavaParserConstants.LPAREN),
+                new CsmChild(n1),
+                new CsmToken(GeneratedJavaParserConstants.RPAREN),
+                new CsmChild(n2)));
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(a, b);
+        assertEquals(4, differenceElements.size());
+        assertEquals(added(new CsmToken(GeneratedJavaParserConstants.LPAREN)), differenceElements.get(0));
+        assertEquals(added(new CsmChild(n1)), differenceElements.get(1));
+        assertEquals(added(new CsmToken(GeneratedJavaParserConstants.RPAREN)), differenceElements.get(2));
+        assertEquals(added(new CsmChild(n2)), differenceElements.get(3));
+    }
+
+    @Test
+    void calculateDifferenceBIsEmpty() {
+        Node n1 = new FieldDeclaration();
+        Node n2 = new MethodDeclaration();
+
+        LexicalDifferenceCalculator.CalculatedSyntaxModel a = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Arrays.asList(
+                new CsmToken(GeneratedJavaParserConstants.LPAREN),
+                new CsmChild(n1),
+                new CsmToken(GeneratedJavaParserConstants.RPAREN),
+                new CsmChild(n2)));
+        LexicalDifferenceCalculator.CalculatedSyntaxModel b = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(a, b);
+        assertEquals(4, differenceElements.size());
+        assertEquals(removed(new CsmToken(GeneratedJavaParserConstants.LPAREN)), differenceElements.get(0));
+        assertEquals(removed(new CsmChild(n1)), differenceElements.get(1));
+        assertEquals(removed(new CsmToken(GeneratedJavaParserConstants.RPAREN)), differenceElements.get(2));
+        assertEquals(removed(new CsmChild(n2)), differenceElements.get(3));
+    }
+
+    @Test
+    void compilationUnitExampleWithPackageSetDiff() {
+        considerCode("class A {}");
+        CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
+        PackageDeclaration packageDeclaration = new PackageDeclaration(new Name(new Name("foo"), "bar"));
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, cu);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, cu, ObservableProperty.PACKAGE_DECLARATION, null, packageDeclaration);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        assertEquals(3, differenceElements.size());
+        assertEquals(added(new CsmChild(packageDeclaration)), differenceElements.get(0));
+        assertEquals(kept(new CsmChild(cu.getType(0))), differenceElements.get(1));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(2));
+    }
+
+    @Test
+    void annotationDeclarationExampleWithModifierAdded() throws IOException {
+        considerExample("AnnotationDeclaration_Example1_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.MODIFIERS, new NodeList<>(), createModifierList(PUBLIC));
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        DifferenceElementCalculator.removeIndentationElements(differenceElements);
+        int i = 0;
+        assertEquals(added(new CsmChild(Modifier.publicModifier())), differenceElements.get(i++));
+        assertEquals(added(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void annotationDeclarationExampleWithNameChanged() throws IOException {
+        considerExample("AnnotationDeclaration_Example1_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
+        SimpleName newName = new SimpleName("NewName");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.NAME,
+                annotationDeclaration.getName(), newName);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        DifferenceElementCalculator.removeIndentationElements(differenceElements);
+        int i = 0;
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(removed(new CsmChild(annotationDeclaration.getName())), differenceElements.get(i++));
+        assertEquals(added(new CsmChild(newName)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void annotationDeclarationExampleWithJavadocAdded() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        JavadocComment comment = new JavadocComment("Cool this annotation!");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.COMMENT, null, comment);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        DifferenceElementCalculator.removeIndentationElements(differenceElements);
+        int i = 0;
+        assertEquals(kept(new CsmChild(Modifier.publicModifier())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void annotationDeclarationExampleWithJavadocRemoved() throws IOException {
+        considerExample("AnnotationDeclaration_Example9_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.COMMENT, annotationDeclaration.getComment().get(), null);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        DifferenceElementCalculator.removeIndentationElements(differenceElements);
+        int i = 0;
+        assertEquals(kept(new CsmChild(Modifier.publicModifier())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void annotationDeclarationExampleWithModifierRemoved() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.MODIFIERS, createModifierList(PUBLIC), new NodeList<>());
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        DifferenceElementCalculator.removeIndentationElements(differenceElements);
+        int i = 0;
+        assertEquals(removed(new CsmChild(Modifier.publicModifier())), differenceElements.get(i++));
+        assertEquals(removed(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void removeDefaultValueInAnnotationMemberDeclaration() {
+        AnnotationMemberDeclaration md = considerAmd("int foo() default 10;");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(md, ObservableProperty.DEFAULT_VALUE, md.getDefaultValue(), null);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        int i = 0;
+        assertEquals(kept(new CsmChild(md.getType())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(md.getName())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), differenceElements.get(i++));
+        assertEquals(removed(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(removed(new CsmToken(GeneratedJavaParserConstants._DEFAULT)), differenceElements.get(i++));
+        assertEquals(removed(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(removed(new CsmChild(md.getDefaultValue().get())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.SEMICOLON)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void addedDefaultValueInAnnotationMemberDeclaration() {
+        AnnotationMemberDeclaration md = considerAmd("int foo();");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
+        Expression defaultValue = new IntegerLiteralExpr(("10"));
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(md, ObservableProperty.DEFAULT_VALUE, null, defaultValue);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        int i = 0;
+        assertEquals(kept(new CsmChild(md.getType())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(md.getName())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), differenceElements.get(i++));
+        assertEquals(added(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(added(new CsmToken(GeneratedJavaParserConstants._DEFAULT)), differenceElements.get(i++));
+        assertEquals(added(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(added(new CsmChild(defaultValue)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.SEMICOLON)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void addedModifierToConstructorDeclaration() {
+        ConstructorDeclaration cd = considerCd("A(){}");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(cd);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(cd, ObservableProperty.MODIFIERS,
+                new NodeList<>(), createModifierList(PUBLIC));
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        int i = 0;
+        assertEquals(added(new CsmChild(Modifier.publicModifier())), differenceElements.get(i++));
+        assertEquals(added(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(cd.getName())), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), differenceElements.get(i++));
+        assertEquals(kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(kept(new CsmChild(cd.getBody())), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void replacingNameForEnumConstantDeclaration() {
+        EnumConstantDeclaration ecd = considerEcd("A");
+        SimpleName newName = new SimpleName("B");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(ecd);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(ecd, ObservableProperty.NAME,
+                ecd.getName(), newName);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        int i = 0;
+        assertEquals(DifferenceElement.removed(new CsmChild(ecd.getName())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.added(new CsmChild(newName)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void addingStatementToEmptyMethodBody() {
+        String code = "class A { void foo(char p1, int p2) {} }";
+        considerCode(code);
+
+        Statement s = new ExpressionStmt(new BinaryExpr(
+                new IntegerLiteralExpr("10"), new IntegerLiteralExpr("2"), BinaryExpr.Operator.PLUS
+        ));
+        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(m.getBody().get());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterListAddition(m.getBody().get(), ObservableProperty.STATEMENTS, 0, s);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        int i = 0;
+        assertEquals(DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.added(new CsmIndent()), differenceElements.get(i++));
+        assertEquals(DifferenceElement.added(new CsmChild(s)), differenceElements.get(i++));
+        assertEquals(DifferenceElement.added(new CsmToken(eolTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.added(new CsmUnindent()), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void methodDeclarationRemovingParameter() {
+        MethodDeclaration md = considerMd("public void foo(float f){}");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterListRemoval(md, ObservableProperty.PARAMETERS, 0);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        int i = 0;
+        assertEquals(DifferenceElement.kept(new CsmChild(Modifier.publicModifier())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmChild(md.getType())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmChild(md.getName())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), differenceElements.get(i++));
+        assertEquals(DifferenceElement.removed(new CsmChild(md.getParameter(0))), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmChild(md.getBody().get())), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    @Test
+    void methodDeclarationAddingParameter() {
+        MethodDeclaration md = considerMd("public void foo(){}");
+        Parameter newParameter = new Parameter(new ArrayType(PrimitiveType.intType()), new SimpleName("foo"));
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterListAddition(md, ObservableProperty.PARAMETERS, 0, newParameter);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(csmOriginal, csmChanged);
+        int i = 0;
+        assertEquals(DifferenceElement.kept(new CsmChild(Modifier.publicModifier())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmChild(md.getType())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmChild(md.getName())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), differenceElements.get(i++));
+        assertEquals(DifferenceElement.added(new CsmChild(newParameter)), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmToken(spaceTokenKind())), differenceElements.get(i++));
+        assertEquals(DifferenceElement.kept(new CsmChild(md.getBody().get())), differenceElements.get(i++));
+        assertEquals(i, differenceElements.size());
+    }
+
+    private AnnotationMemberDeclaration considerAmd(String code) {
+        considerCode("@interface AD { " + code + " }");
+        return (AnnotationMemberDeclaration)cu.getAnnotationDeclarationByName("AD").get().getMember(0);
+    }
+
+    private ConstructorDeclaration considerCd(String code) {
+        considerCode("class A { " + code + " }");
+        return (ConstructorDeclaration) cu.getType(0).getMembers().get(0);
+    }
+
+    private EnumConstantDeclaration considerEcd(String code) {
+        considerCode("enum A { " + code + " }");
+        return ((EnumDeclaration)cu.getType(0)).getEntries().get(0);
+    }
+
+    private MethodDeclaration considerMd(String code) {
+        considerCode("class A { " + code + " }");
+        return (MethodDeclaration) cu.getType(0).getMembers().get(0);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculatorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculatorTest.java
new file mode 100644
index 0000000..1fec241
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculatorTest.java
@@ -0,0 +1,304 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.GeneratedJavaParserConstants;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.comments.JavadocComment;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.printer.ConcreteSyntaxModel;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.List;
+
+import static com.github.javaparser.TokenTypes.eolTokenKind;
+import static com.github.javaparser.TokenTypes.spaceTokenKind;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class LexicalDifferenceCalculatorTest extends AbstractLexicalPreservingTest {
+
+    @Test
+    void compilationUnitExampleOriginal() {
+        considerCode("class A {}");
+        CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, cu);
+        assertEquals(2, csmOriginal.elements.size());
+        assertEquals(new CsmChild(cu.getType(0)), csmOriginal.elements.get(0));
+        assertEquals(new CsmToken(eolTokenKind()), csmOriginal.elements.get(1));
+    }
+
+    @Test
+    void compilationUnitExampleWithPackageSet() {
+        considerCode("class A {}");
+        CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
+        PackageDeclaration packageDeclaration = new PackageDeclaration(new Name(new Name("foo"), "bar"));
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, cu, ObservableProperty.PACKAGE_DECLARATION, null, packageDeclaration);
+        assertEquals(3, csmChanged.elements.size());
+        assertEquals(new CsmChild(packageDeclaration), csmChanged.elements.get(0));
+        assertEquals(new CsmChild(cu.getType(0)), csmChanged.elements.get(1));
+        assertEquals(new CsmToken(eolTokenKind()), csmChanged.elements.get(2));
+    }
+
+    @Test
+    void annotationDeclarationModifiersExampleOriginal() throws IOException {
+        considerExample("AnnotationDeclaration_Example1_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
+        csm.removeIndentationElements();
+        int i = 0;
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
+        assertEquals(i, csm.elements.size());
+    }
+
+    @Test
+    void annotationDeclarationModifiersExampleModified() throws IOException {
+        considerExample("AnnotationDeclaration_Example1_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.MODIFIERS, new NodeList<>(), createModifierList(PUBLIC));
+        csm.removeIndentationElements();
+        int i = 0;
+        assertEquals(new CsmChild(Modifier.publicModifier()), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
+        assertEquals(i, csm.elements.size());
+    }
+
+    @Test
+    void annotationDeclarationNameExampleModified() throws IOException {
+        considerExample("AnnotationDeclaration_Example1_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        SimpleName newName = new SimpleName("NewName");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.NAME,
+                annotationDeclaration.getName(), newName);
+        csm.removeIndentationElements();
+        int i = 0;
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(newName), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
+        assertEquals(i, csm.elements.size());
+    }
+
+    @Test
+    void annotationDeclarationJavadocExampleOriginal() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
+        csm.removeIndentationElements();
+        int i = 0;
+        assertEquals(new CsmChild(Modifier.publicModifier()), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
+        assertEquals(i, csm.elements.size());
+    }
+
+    @Test
+    void annotationDeclarationJavadocExampleAddingJavadoc() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
+        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
+        JavadocComment comment = new JavadocComment("Cool this annotation!");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.COMMENT, null, comment);
+        csm.removeIndentationElements();
+        int i = 0;
+        assertEquals(new CsmChild(Modifier.publicModifier()), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
+        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
+        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
+        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
+        assertEquals(i, csm.elements.size());
+    }
+
+    @Test
+    void simpleEnumConstantDeclaration() {
+        EnumConstantDeclaration ecd = considerEcd("A");
+        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(ecd);
+
+        int i = 0;
+        assertEquals(new CsmChild(ecd.getName()), csm.elements.get(i++));
+        assertEquals(i, csm.elements.size());
+    }
+
+    @Test
+    void csmModelAfterAddingStatementToEmptyBlock() throws IOException {
+        LexicalDifferenceCalculator ldc = new LexicalDifferenceCalculator();
+        considerExample("ASimpleClassWithMoreFormatting_step3");
+
+        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
+                .getMethodsByName("setAField").get(0);
+        Statement assignStatement = new ExpressionStmt(
+                new AssignExpr(
+                        new FieldAccessExpr(new ThisExpr(),"aField"),
+                        new NameExpr("aField"),
+                        AssignExpr.Operator.ASSIGN
+                ));
+        LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel =
+                ldc.calculatedSyntaxModelAfterListAddition(
+                        ConcreteSyntaxModel.forClass(BlockStmt.class),
+                        ObservableProperty.STATEMENTS,
+                        setter.getBody().get().getStatements(),
+                        0,
+                        assignStatement);
+        int index = 0;
+        assertEquals(CsmElement.token(GeneratedJavaParserConstants.LBRACE), calculatedSyntaxModel.elements.get(index++));
+        assertEquals(CsmElement.newline(), calculatedSyntaxModel.elements.get(index++));
+        assertEquals(CsmElement.indent(), calculatedSyntaxModel.elements.get(index++));
+        assertTrue(isChild(calculatedSyntaxModel.elements.get(index++), ExpressionStmt.class));
+        assertEquals(CsmElement.newline(), calculatedSyntaxModel.elements.get(index++));
+        assertEquals(CsmElement.unindent(), calculatedSyntaxModel.elements.get(index++));
+        assertEquals(CsmElement.token(GeneratedJavaParserConstants.RBRACE), calculatedSyntaxModel.elements.get(index++));
+        assertEquals(index, calculatedSyntaxModel.elements.size());
+    }
+
+    @Test
+    void differenceAfterddingStatementToEmptyBlock() throws IOException {
+        LexicalDifferenceCalculator ldc = new LexicalDifferenceCalculator();
+        considerExample("ASimpleClassWithMoreFormatting_step3");
+
+        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
+                .getMethodsByName("setAField").get(0);
+        Statement assignStatement = new ExpressionStmt(
+                new AssignExpr(
+                        new FieldAccessExpr(new ThisExpr(),"aField"),
+                        new NameExpr("aField"),
+                        AssignExpr.Operator.ASSIGN
+                ));
+        List<DifferenceElement> differenceElements = ldc.calculateListAdditionDifference(
+                ObservableProperty.STATEMENTS,
+                setter.getBody().get().getStatements(),
+                0,
+                assignStatement);
+        int index = 0;
+        assertEquals(DifferenceElement.kept(CsmElement.token(GeneratedJavaParserConstants.LBRACE)), differenceElements.get(index++));
+        assertEquals(DifferenceElement.kept(CsmElement.newline()), differenceElements.get(index++));
+        assertEquals(DifferenceElement.added(CsmElement.indent()), differenceElements.get(index++));
+        assertTrue(isAddedChild(differenceElements.get(index++), ExpressionStmt.class));
+        assertEquals(DifferenceElement.added(CsmElement.newline()), differenceElements.get(index++));
+        assertEquals(DifferenceElement.added(CsmElement.unindent()), differenceElements.get(index++));
+        assertEquals(DifferenceElement.kept(CsmElement.token(GeneratedJavaParserConstants.RBRACE)), differenceElements.get(index++));
+        assertEquals(index, differenceElements.size());
+    }
+
+    private boolean isAddedChild(DifferenceElement element, Class<? extends Node> childClass) {
+        return element.isAdded() && isChild(element.getElement(), childClass);
+    }
+
+    private boolean isChild(CsmElement element, Class<? extends Node> childClass) {
+        return element instanceof CsmChild && childClass.isInstance(((CsmChild)element).getChild());
+    }
+
+    protected EnumConstantDeclaration considerEcd(String code) {
+        considerCode("enum A { " + code + " }");
+        return ((EnumDeclaration)cu.getType(0)).getEntries().get(0);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java
new file mode 100644
index 0000000..7b6afe0
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java
@@ -0,0 +1,1224 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter.NODE_TEXT_DATA;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+
+import com.github.javaparser.GeneratedJavaParserConstants;
+import com.github.javaparser.ast.*;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.CatchClause;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.stmt.TryStmt;
+import com.github.javaparser.ast.type.Type;
+import com.github.javaparser.ast.type.UnionType;
+import com.github.javaparser.ast.type.VoidType;
+import com.github.javaparser.ast.visitor.ModifierVisitor;
+import com.github.javaparser.ast.visitor.Visitable;
+
+class LexicalPreservingPrinterTest extends AbstractLexicalPreservingTest {
+    private NodeText getTextForNode(Node node) {
+        return node.getData(NODE_TEXT_DATA);
+    }
+
+
+    //
+    // Tests on TextNode definition
+    //
+
+    @Test
+    void checkNodeTextCreatedForSimplestClass() {
+        considerCode("class A {}");
+
+        // CU
+        assertEquals(1, getTextForNode(cu).numberOfElements());
+        assertTrue(getTextForNode(cu).getTextElement(0) instanceof ChildTextElement);
+        assertEquals(cu.getClassByName("A").get(), ((ChildTextElement) getTextForNode(cu).getTextElement(0)).getChild());
+
+        // Class
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        assertEquals(7, getTextForNode(classA).numberOfElements());
+        assertEquals("class", getTextForNode(classA).getTextElement(0).expand());
+        assertEquals(" ", getTextForNode(classA).getTextElement(1).expand());
+        assertEquals("A", getTextForNode(classA).getTextElement(2).expand());
+        assertEquals(" ", getTextForNode(classA).getTextElement(3).expand());
+        assertEquals("{", getTextForNode(classA).getTextElement(4).expand());
+        assertEquals("}", getTextForNode(classA).getTextElement(5).expand());
+        assertEquals("", getTextForNode(classA).getTextElement(6).expand());
+        assertTrue(getTextForNode(classA).getTextElement(6) instanceof TokenTextElement);
+        assertEquals(GeneratedJavaParserConstants.EOF, ((TokenTextElement) getTextForNode(classA).getTextElement(6)).getTokenKind());
+    }
+
+    @Test
+    void checkNodeTextCreatedForField() {
+        String code = "class A {int i;}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        FieldDeclaration fd = classA.getFieldByName("i").get();
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(fd);
+        assertEquals(Arrays.asList("int", " ", "i", ";"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedForVariableDeclarator() {
+        String code = "class A {int i;}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        FieldDeclaration fd = classA.getFieldByName("i").get();
+        VariableDeclarator vd = fd.getVariables().get(0);
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(vd);
+        assertEquals(Arrays.asList("i"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedForMethod() {
+        String code = "class A {void foo(int p1, float p2) { }}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        MethodDeclaration md = classA.getMethodsByName("foo").get(0);
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
+        assertEquals(Arrays.asList("void", " ", "foo", "(", "int p1", ",", " ", "float p2", ")", " ", "{ }"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedForMethodParameter() {
+        String code = "class A {void foo(int p1, float p2) { }}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        MethodDeclaration md = classA.getMethodsByName("foo").get(0);
+        Parameter p1 = md.getParameterByName("p1").get();
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(p1);
+        assertEquals(Arrays.asList("int", " ", "p1"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedForPrimitiveType() {
+        String code = "class A {void foo(int p1, float p2) { }}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        MethodDeclaration md = classA.getMethodsByName("foo").get(0);
+        Parameter p1 = md.getParameterByName("p1").get();
+        Type t = p1.getType();
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(t);
+        assertEquals(Arrays.asList("int"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedForSimpleImport() {
+        String code = "import a.b.c.D;";
+        considerCode(code);
+
+        ImportDeclaration imp = (ImportDeclaration) cu.getChildNodes().get(0);
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(imp);
+        assertEquals(Arrays.asList("import", " ", "a.b.c.D", ";", ""),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void addedImportShouldBePrependedWithEOL() {
+        considerCode("import a;" + EOL + "class X{}");
+
+        cu.addImport("b");
+
+        assertEqualsNoEol("import a;\nimport b;\nclass X{}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void checkNodeTextCreatedGenericType() {
+        String code = "class A {ParseResult<T> result;}";
+        considerCode(code);
+
+        FieldDeclaration field = cu.getClassByName("A").get().getFieldByName("result").get();
+        Node t = field.getCommonType();
+        Node t2 = field.getVariable(0).getType();
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(field);
+        assertEquals(Arrays.asList("ParseResult", "<", "T", ">", " ", "result", ";"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedAnnotationDeclaration() {
+        String code = "public @interface ClassPreamble { String author(); }";
+        considerCode(code);
+
+        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(ad);
+        assertEquals(Arrays.asList("public", " ", "@", "interface", " ", "ClassPreamble", " ", "{", " ", "String author();", " ", "}", ""),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedAnnotationMemberDeclaration() {
+        String code = "public @interface ClassPreamble { String author(); }";
+        considerCode(code);
+
+        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
+        AnnotationMemberDeclaration md = (AnnotationMemberDeclaration) ad.getMember(0);
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
+        assertEquals(Arrays.asList("String", " ", "author", "(", ")", ";"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedAnnotationMemberDeclarationWithArrayType() {
+        String code = "public @interface ClassPreamble { String[] author(); }";
+        considerCode(code);
+
+        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
+        AnnotationMemberDeclaration md = (AnnotationMemberDeclaration) ad.getMember(0);
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
+        assertEquals(Arrays.asList("String[]", " ", "author", "(", ")", ";"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedAnnotationMemberDeclarationArrayType() {
+        String code = "public @interface ClassPreamble { String[] author(); }";
+        considerCode(code);
+
+        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
+        AnnotationMemberDeclaration md = ad.getMember(0).asAnnotationMemberDeclaration();
+        Type type = md.getType();
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(type);
+        assertEquals(Arrays.asList("String", "[", "]"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedAnnotationMemberDeclarationWithComment() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+
+        AnnotationMemberDeclaration md = cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(5).asAnnotationMemberDeclaration();
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
+        assertEquals(Arrays.asList("String[]", " ", "reviewers", "(", ")", ";"),
+                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedArrayCreationLevelWithoutExpression() {
+        considerExpression("new int[]");
+
+        ArrayCreationExpr arrayCreationExpr = expression.asArrayCreationExpr();
+        ArrayCreationLevel arrayCreationLevel = arrayCreationExpr.getLevels().get(0);
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(arrayCreationLevel);
+        assertEquals(Arrays.asList("[", "]"),
+                nodeText.getElements().stream().map(TextElement::expand).filter(e -> !e.isEmpty()).collect(Collectors.toList()));
+    }
+
+    @Test
+    void checkNodeTextCreatedArrayCreationLevelWith() {
+        considerExpression("new int[123]");
+
+        ArrayCreationExpr arrayCreationExpr = expression.asArrayCreationExpr();
+        ArrayCreationLevel arrayCreationLevel = arrayCreationExpr.getLevels().get(0);
+        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(arrayCreationLevel);
+        assertEquals(Arrays.asList("[", "123", "]"),
+                nodeText.getElements().stream().map(TextElement::expand).filter(e -> !e.isEmpty()).collect(Collectors.toList()));
+    }
+
+    //
+    // Tests on findIndentation
+    //
+
+    @Test
+    void findIndentationForAnnotationMemberDeclarationWithoutComment() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        Node node = cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(4);
+        List<TokenTextElement> indentation = LexicalPreservingPrinter.findIndentation(node);
+        assertEquals(Arrays.asList(" ", " ", " "), indentation.stream().map(TokenTextElement::expand).collect(Collectors.toList()));
+    }
+
+    @Test
+    void findIndentationForAnnotationMemberDeclarationWithComment() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        Node node = cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(5);
+        List<TokenTextElement> indentation = LexicalPreservingPrinter.findIndentation(node);
+        assertEquals(Arrays.asList(" ", " ", " "), indentation.stream().map(TokenTextElement::expand).collect(Collectors.toList()));
+    }
+
+    //
+    // Tests on printing
+    //
+
+    @Test
+    void printASuperSimpleCUWithoutChanges() {
+        String code = "class A {}";
+        considerCode(code);
+
+        assertEquals(code, LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void printASuperSimpleClassWithAFieldAdded() {
+        String code = "class A {}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        classA.addField("int", "myField");
+        assertEquals("class A {" + EOL + "    int myField;" + EOL + "}", LexicalPreservingPrinter.print(classA));
+    }
+
+    @Test
+    void printASuperSimpleClassWithoutChanges() {
+        String code = "class A {}";
+        considerCode(code);
+
+        assertEquals(code, LexicalPreservingPrinter.print(cu.getClassByName("A").get()));
+    }
+
+    @Test
+    void printASimpleCUWithoutChanges() {
+        String code = "class /*a comment*/ A {\t\t" + EOL + " int f;" + EOL + EOL + EOL + "         void foo(int p  ) { return  'z'  \t; }}";
+        considerCode(code);
+
+        assertEquals(code, LexicalPreservingPrinter.print(cu));
+        assertEquals(code, LexicalPreservingPrinter.print(cu.getClassByName("A").get()));
+        assertEquals("void foo(int p  ) { return  'z'  \t; }", LexicalPreservingPrinter.print(cu.getClassByName("A").get().getMethodsByName("foo").get(0)));
+    }
+
+    @Test
+    void printASimpleClassRemovingAField() {
+        String code = "class /*a comment*/ A {\t\t" + EOL +
+                " int f;" + EOL + EOL + EOL +
+                "         void foo(int p  ) { return  'z'  \t; }}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration c = cu.getClassByName("A").get();
+        c.getMembers().remove(0);
+        assertEquals("class /*a comment*/ A {\t\t" + EOL +
+                EOL +
+                "         void foo(int p  ) { return  'z'  \t; }}", LexicalPreservingPrinter.print(c));
+    }
+
+    @Test
+    void printASimpleClassRemovingAMethod() {
+        String code = "class /*a comment*/ A {\t\t" + EOL +
+                " int f;" + EOL + EOL + EOL +
+                "         void foo(int p  ) { return  'z'  \t; }" + EOL +
+                " int g;}";
+        considerCode(code);
+
+        ClassOrInterfaceDeclaration c = cu.getClassByName("A").get();
+        c.getMembers().remove(1);
+        assertEquals("class /*a comment*/ A {\t\t" + EOL +
+                " int f;" + EOL + EOL + EOL +
+                " int g;}", LexicalPreservingPrinter.print(c));
+    }
+
+    @Test
+    void printASimpleMethodAddingAParameterToAMethodWithZeroParameters() {
+        String code = "class A { void foo() {} }";
+        considerCode(code);
+
+        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
+        m.addParameter("float", "p1");
+        assertEquals("void foo(float p1) {}", LexicalPreservingPrinter.print(m));
+    }
+
+    @Test
+    void printASimpleMethodAddingAParameterToAMethodWithOneParameter() {
+        String code = "class A { void foo(char p1) {} }";
+        considerCode(code);
+
+        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
+        m.addParameter("float", "p2");
+        assertEquals("void foo(char p1, float p2) {}", LexicalPreservingPrinter.print(m));
+    }
+
+    @Test
+    void printASimpleMethodRemovingAParameterToAMethodWithOneParameter() {
+        String code = "class A { void foo(float p1) {} }";
+        considerCode(code);
+
+        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
+        m.getParameters().remove(0);
+        assertEquals("void foo() {}", LexicalPreservingPrinter.print(m));
+    }
+
+    @Test
+    void printASimpleMethodRemovingParameterOneFromMethodWithTwoParameters() {
+        String code = "class A { void foo(char p1, int p2) {} }";
+        considerCode(code);
+
+        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
+        m.getParameters().remove(0);
+        assertEquals("void foo(int p2) {}", LexicalPreservingPrinter.print(m));
+    }
+
+    @Test
+    void printASimpleMethodRemovingParameterTwoFromMethodWithTwoParameters() {
+        String code = "class A { void foo(char p1, int p2) {} }";
+        considerCode(code);
+
+        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
+        m.getParameters().remove(1);
+        assertEquals("void foo(char p1) {}", LexicalPreservingPrinter.print(m));
+    }
+
+    @Test
+    void printASimpleMethodAddingAStatement() {
+        String code = "class A { void foo(char p1, int p2) {} }";
+        considerCode(code);
+
+        Statement s = new ExpressionStmt(new BinaryExpr(
+                new IntegerLiteralExpr("10"), new IntegerLiteralExpr("2"), BinaryExpr.Operator.PLUS
+        ));
+        NodeList<Statement> stmts = cu.getClassByName("A").get().getMethodsByName("foo").get(0).getBody().get().getStatements();
+        stmts.add(s);
+        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
+        assertEquals("void foo(char p1, int p2) {" + EOL +
+                "    10 + 2;" + EOL +
+                "}", LexicalPreservingPrinter.print(m));
+    }
+    
+    @Test
+    void printASimpleMethodRemovingAStatementCRLF() {
+    	printASimpleMethodRemovingAStatement("\r\n");
+    }
+    
+    @Test
+    void printASimpleMethodRemovingAStatementLF() {
+    	printASimpleMethodRemovingAStatement("\n");
+    }
+    
+    @Test
+    void printASimpleMethodRemovingAStatementCR() {
+    	printASimpleMethodRemovingAStatement("\r");
+    }
+    
+    private void printASimpleMethodRemovingAStatement(String eol) {
+    	String code = "class A {" 						+ eol
+    			+ "\t"		+  "foo(int a, int b) {"	+ eol
+    			+ "\t\t" 	+ "int result = a * b;"		+ eol
+    			+ "\t\t" 	+ "return a * b;"			+ eol
+    			+ "\t"		+ "}"						+ eol
+    			+ "}";
+    			
+    	
+    	CompilationUnit cu = parse(code);
+    	LexicalPreservingPrinter.setup(cu);
+    	ExpressionStmt stmt = cu.findAll(ExpressionStmt.class).get(0);
+    	stmt.remove();
+    	
+        assertEquals("class A {"						+ eol
+    			+ "\t"		+  "foo(int a, int b) {"	+ eol
+    			+ "\t\t" 	+ "return a * b;"			+ eol
+    			+ "\t"		+ "}"						+ eol
+    			+ "}", LexicalPreservingPrinter.print(cu)); 
+    }
+    
+    @Test
+    void printASimpleImport() {
+        String code = "import a.b.c.D;";
+        considerCode(code);
+
+        ImportDeclaration imp = (ImportDeclaration) cu.getChildNodes().get(0);
+        assertEquals("import a.b.c.D;", LexicalPreservingPrinter.print(imp));
+    }
+
+    @Test
+    void printAnotherImport() {
+        String code = "import com.github.javaparser.ast.CompilationUnit;";
+        considerCode(code);
+
+        ImportDeclaration imp = (ImportDeclaration) cu.getChildNodes().get(0);
+        assertEquals("import com.github.javaparser.ast.CompilationUnit;", LexicalPreservingPrinter.print(imp));
+    }
+
+    @Test
+    void printAStaticImport() {
+        String code = "import static com.github.javaparser.ParseStart.*;";
+        considerCode(code);
+
+        ImportDeclaration imp = (ImportDeclaration) cu.getChildNodes().get(0);
+        assertEquals("import static com.github.javaparser.ParseStart.*;", LexicalPreservingPrinter.print(imp));
+    }
+
+    @Test
+    void checkAnnidatedTypeParametersPrinting() {
+        String code = "class A { private final Stack<Iterator<Triple>> its = new Stack<Iterator<Triple>>(); }";
+        considerCode(code);
+        assertEquals("class A { private final Stack<Iterator<Triple>> its = new Stack<Iterator<Triple>>(); }", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void printASingleCatch() {
+        String code = "class A {{try { doit(); } catch (Exception e) {}}}";
+        considerCode(code);
+
+        assertEquals("class A {{try { doit(); } catch (Exception e) {}}}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void printAMultiCatch() {
+        String code = "class A {{try { doit(); } catch (Exception | AssertionError e) {}}}";
+        considerCode(code);
+
+        assertEquals("class A {{try { doit(); } catch (Exception | AssertionError e) {}}}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void printASingleCatchType() {
+        String code = "class A {{try { doit(); } catch (Exception e) {}}}";
+        considerCode(code);
+        InitializerDeclaration initializerDeclaration = (InitializerDeclaration) cu.getType(0).getMembers().get(0);
+        TryStmt tryStmt = (TryStmt) initializerDeclaration.getBody().getStatements().get(0);
+        CatchClause catchClause = tryStmt.getCatchClauses().get(0);
+        Type catchType = catchClause.getParameter().getType();
+
+        assertEquals("Exception", LexicalPreservingPrinter.print(catchType));
+    }
+
+    @Test
+    void printUnionType() {
+        String code = "class A {{try { doit(); } catch (Exception | AssertionError e) {}}}";
+        considerCode(code);
+        InitializerDeclaration initializerDeclaration = (InitializerDeclaration) cu.getType(0).getMembers().get(0);
+        TryStmt tryStmt = (TryStmt) initializerDeclaration.getBody().getStatements().get(0);
+        CatchClause catchClause = tryStmt.getCatchClauses().get(0);
+        UnionType unionType = (UnionType) catchClause.getParameter().getType();
+
+        assertEquals("Exception | AssertionError", LexicalPreservingPrinter.print(unionType));
+    }
+
+    @Test
+    void printParameterHavingUnionType() {
+        String code = "class A {{try { doit(); } catch (Exception | AssertionError e) {}}}";
+        considerCode(code);
+        InitializerDeclaration initializerDeclaration = (InitializerDeclaration) cu.getType(0).getMembers().get(0);
+        TryStmt tryStmt = (TryStmt) initializerDeclaration.getBody().getStatements().get(0);
+        CatchClause catchClause = tryStmt.getCatchClauses().get(0);
+        Parameter parameter = catchClause.getParameter();
+
+        assertEquals("Exception | AssertionError e", LexicalPreservingPrinter.print(parameter));
+    }
+
+    @Test
+    void printLambaWithUntypedParams() {
+        String code = "class A {Function<String,String> f = a -> a;}";
+        considerCode(code);
+
+        assertEquals("class A {Function<String,String> f = a -> a;}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void printAModuleInfoSpecificKeywordUsedAsIdentifier1() {
+        considerCode("class module { }");
+
+        cu.getClassByName("module").get().setName("xyz");
+
+        assertEquals("class xyz { }", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void printAModuleInfoSpecificKeywordUsedAsIdentifier2() {
+        considerCode("class xyz { }");
+
+        cu.getClassByName("xyz").get().setName("module");
+
+        assertEquals("class module { }", LexicalPreservingPrinter.print(cu));
+    }
+
+    // Issue 823: setPackageDeclaration on CU starting with a comment
+    @Test
+    void reactToSetPackageDeclarationOnCuStartingWithComment() {
+        considerCode("// Hey, this is a comment\n" +
+                "\n" +
+                "\n" +
+                "// Another one\n" +
+                "\n" +
+                "class A {}");
+        cu.setPackageDeclaration("org.javaparser.lexicalpreservation.examples");
+    }
+
+    @Test
+    void printLambdaIntersectionTypeAssignment() {
+        String code = "class A {" + EOL +
+                "  void f() {" + EOL +
+                "    Runnable r = (Runnable & Serializable) (() -> {});" + EOL +
+                "    r = (Runnable & Serializable)() -> {};" + EOL +
+                "    r = (Runnable & I)() -> {};" + EOL +
+                "  }}";
+        considerCode(code);
+
+        assertEquals(code, LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void printLambdaIntersectionTypeReturn() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        considerCode(code);
+
+        assertEquals(code, LexicalPreservingPrinter.print(cu));
+    }
+
+    // See issue #855
+    @Test
+    void handleOverrideAnnotation() {
+        String code = "public class TestPage extends Page {" + EOL +
+                EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes()
+                .forEach(type -> type.getMembers()
+                        .forEach(member -> {
+                            if (member instanceof MethodDeclaration) {
+                                MethodDeclaration methodDeclaration = (MethodDeclaration) member;
+                                if (!methodDeclaration.getAnnotationByName("Override").isPresent()) {
+                                    methodDeclaration.addAnnotation("Override");
+                                }
+                            }
+                        }));
+        assertEquals("public class TestPage extends Page {" + EOL +
+                EOL +
+                "   @Override()" + EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void preserveSpaceAsIsForASimpleClassWithMoreFormatting() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting");
+        assertEquals(readExample("ASimpleClassWithMoreFormatting"), LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void renameASimpleClassWithMoreFormatting() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting");
+
+        cu.getClassByName("ASimpleClass").get()
+                .setName("MyRenamedClass");
+        assertEquals(readExample("ASimpleClassWithMoreFormatting_step1"), LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void theLexicalPreservationStringForAnAddedMethodShouldBeIndented() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting");
+
+        cu.getClassByName("ASimpleClass").get()
+                .setName("MyRenamedClass");
+        MethodDeclaration setter = cu
+                .getClassByName("MyRenamedClass").get()
+                .addMethod("setAField", PUBLIC);
+        assertEquals("public void setAField() {" + EOL +
+                "    }", LexicalPreservingPrinter.print(setter));
+    }
+
+    @Test
+    void addMethodToASimpleClassWithMoreFormatting() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting");
+
+        cu.getClassByName("ASimpleClass").get()
+                .setName("MyRenamedClass");
+        MethodDeclaration setter = cu
+                .getClassByName("MyRenamedClass").get()
+                .addMethod("setAField", PUBLIC);
+        assertEquals(readExample("ASimpleClassWithMoreFormatting_step2"), LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void addingParameterToAnAddedMethodInASimpleClassWithMoreFormatting() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting");
+
+        cu.getClassByName("ASimpleClass").get()
+                .setName("MyRenamedClass");
+        MethodDeclaration setter = cu
+                .getClassByName("MyRenamedClass").get()
+                .addMethod("setAField", PUBLIC);
+        setter.addParameter("boolean", "aField");
+        assertEquals(readExample("ASimpleClassWithMoreFormatting_step3"), LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void findIndentationOfEmptyMethod() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting_step3");
+
+        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
+                .getMethodsByName("setAField").get(0);
+        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter).size());
+        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter.getBody().get()).size());
+    }
+
+    @Test
+    void findIndentationOfMethodWithStatements() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting_step4");
+
+        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
+                .getMethodsByName("setAField").get(0);
+        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter).size());
+        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter.getBody().get()).size());
+        assertEquals(8, LexicalPreservingPrinter.findIndentation(setter.getBody().get().getStatement(0)).size());
+    }
+
+    @Test
+    void addingStatementToAnAddedMethodInASimpleClassWithMoreFormatting() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting");
+
+        cu.getClassByName("ASimpleClass").get()
+                .setName("MyRenamedClass");
+        MethodDeclaration setter = cu
+                .getClassByName("MyRenamedClass").get()
+                .addMethod("setAField", PUBLIC);
+        setter.addParameter("boolean", "aField");
+        setter.getBody().get().getStatements().add(new ExpressionStmt(
+                new AssignExpr(
+                        new FieldAccessExpr(new ThisExpr(), "aField"),
+                        new NameExpr("aField"),
+                        AssignExpr.Operator.ASSIGN
+                )));
+        assertEquals(readExample("ASimpleClassWithMoreFormatting_step4"), LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void addingStatementToAnAddedMethodInASimpleClassWithMoreFormattingFromStep3() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting_step3");
+
+        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
+                .getMethodsByName("setAField").get(0);
+        setter.getBody().get().getStatements().add(new ExpressionStmt(
+                new AssignExpr(
+                        new FieldAccessExpr(new ThisExpr(), "aField"),
+                        new NameExpr("aField"),
+                        AssignExpr.Operator.ASSIGN
+                )));
+        assertEquals(readExample("ASimpleClassWithMoreFormatting_step4"), LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void nodeTextForMethod() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting_step4");
+
+        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
+                .getMethodsByName("setAField").get(0);
+        NodeText nodeText;
+
+        nodeText = getTextForNode(setter);
+        int index = 0;
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(Modifier.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(VoidType.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(SimpleName.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LPAREN));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(Parameter.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RPAREN));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(BlockStmt.class));
+        assertEquals(index, nodeText.getElements().size());
+
+        nodeText = getTextForNode(setter.getBody().get());
+        index = 0;
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LBRACE));
+        assertTrue(nodeText.getElements().get(index++).isNewline());
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(ExpressionStmt.class));
+        assertTrue(nodeText.getElements().get(index++).isNewline());
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RBRACE));
+        assertEquals(index, nodeText.getElements().size());
+
+        nodeText = getTextForNode(setter.getBody().get().getStatement(0));
+        index = 0;
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(AssignExpr.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SEMICOLON));
+        assertEquals(index, nodeText.getElements().size());
+    }
+
+    @Test
+    void nodeTextForModifiedMethod() throws IOException {
+        considerExample("ASimpleClassWithMoreFormatting_step3");
+
+        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
+                .getMethodsByName("setAField").get(0);
+        setter.getBody().get().getStatements().add(new ExpressionStmt(
+                new AssignExpr(
+                        new FieldAccessExpr(new ThisExpr(), "aField"),
+                        new NameExpr("aField"),
+                        AssignExpr.Operator.ASSIGN
+                )));
+        NodeText nodeText;
+
+        nodeText = getTextForNode(setter);
+        int index = 0;
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(Modifier.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(VoidType.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(SimpleName.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LPAREN));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(Parameter.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RPAREN));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(BlockStmt.class));
+        assertEquals(index, nodeText.getElements().size());
+
+        nodeText = getTextForNode(setter.getBody().get());
+        index = 0;
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LBRACE));
+        assertTrue(nodeText.getElements().get(index++).isNewline());
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(ExpressionStmt.class));
+        assertTrue(nodeText.getElements().get(index++).isNewline());
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RBRACE));
+        assertEquals(index, nodeText.getElements().size());
+
+        nodeText = LexicalPreservingPrinter.getOrCreateNodeText(setter.getBody().get().getStatement(0));
+        index = 0;
+        assertTrue(nodeText.getElements().get(index++).isChildOfClass(AssignExpr.class));
+        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SEMICOLON));
+        assertEquals(index, nodeText.getElements().size());
+    }
+
+    // See issue #926
+    @Test
+    void addASecondStatementToExistingMethod() throws IOException {
+        considerExample("MethodWithOneStatement");
+
+        MethodDeclaration methodDeclaration = cu.getType(0).getMethodsByName("someMethod").get(0);
+        methodDeclaration.getBody().get().getStatements().add(new ExpressionStmt(
+                new VariableDeclarationExpr(
+                        new VariableDeclarator(
+                                parseClassOrInterfaceType("String"),
+                                "test2",
+                                new StringLiteralExpr("")))
+        ));
+        assertEquals("public void someMethod() {" + EOL
+                + "        String test = \"\";" + EOL
+                + "        String test2 = \"\";" + EOL
+        // HACK: The right closing brace should not have indentation because the original method did not introduce indentation, 
+        //however due to necessity this test was left with indentation, in a later version it should be revised.
+                + "    }", LexicalPreservingPrinter.print(methodDeclaration));
+    }
+
+    // See issue #866
+    @Test
+    void moveOverrideAnnotations() {
+        String code = "public class TestPage extends Page {" + EOL +
+                EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   protected @Override void initializePage() {}" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes()
+                .forEach(type -> type.getMembers()
+                        .forEach(member -> member.ifMethodDeclaration(methodDeclaration -> {
+                                if (methodDeclaration.getAnnotationByName("Override").isPresent()) {
+
+                                    while (methodDeclaration.getAnnotations().isNonEmpty()) {
+                                        AnnotationExpr annotationExpr = methodDeclaration.getAnnotations().get(0);
+                                        annotationExpr.remove();
+                                    }
+
+                                    methodDeclaration.addMarkerAnnotation("Override");
+                                }
+                            })));
+        assertEquals("public class TestPage extends Page {" + EOL +
+                EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    // See issue #866
+    @Test
+    void moveOrAddOverrideAnnotations() {
+        String code = "public class TestPage extends Page {" + EOL +
+                EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   protected @Override void initializePage() {}" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes()
+                .forEach(type -> type.getMembers()
+                        .forEach(member -> {
+                            if (member instanceof MethodDeclaration) {
+                                MethodDeclaration methodDeclaration = (MethodDeclaration) member;
+                                if (methodDeclaration.getAnnotationByName("Override").isPresent()) {
+
+                                    while (methodDeclaration.getAnnotations().isNonEmpty()) {
+                                        AnnotationExpr annotationExpr = methodDeclaration.getAnnotations().get(0);
+                                        annotationExpr.remove();
+                                    }
+                                }
+                                methodDeclaration.addMarkerAnnotation("Override");
+                            }
+                        }));
+        assertEquals("public class TestPage extends Page {" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    // See issue #865
+    @Test
+    void handleAddingMarkerAnnotation() {
+        String code = "public class TestPage extends Page {" + EOL +
+                EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes()
+                .forEach(type -> type.getMembers()
+                        .forEach(member -> {
+                            if (member instanceof MethodDeclaration) {
+                                MethodDeclaration methodDeclaration = (MethodDeclaration) member;
+                                if (!methodDeclaration.getAnnotationByName("Override").isPresent()) {
+                                    methodDeclaration.addMarkerAnnotation("Override");
+                                }
+                            }
+                        }));
+        assertEquals("public class TestPage extends Page {" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    // See issue #865
+    @Test
+    void handleOverrideMarkerAnnotation() {
+        String code = "public class TestPage extends Page {" + EOL +
+                EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes()
+                .forEach(type -> type.getMembers()
+                        .forEach(member ->
+                                member.ifMethodDeclaration(methodDeclaration -> methodDeclaration.addMarkerAnnotation("Override")
+                                )));
+        assertEquals("public class TestPage extends Page {" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    // See issue #865
+    @Test
+    void handleOverrideAnnotationAlternative() {
+        String code = "public class TestPage extends Page {" + EOL +
+                EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes()
+                .forEach(type -> type.getMembers()
+                        .forEach(member -> member.ifMethodDeclaration(methodDeclaration -> methodDeclaration.addAnnotation("Override"))));
+        assertEquals("public class TestPage extends Page {" + EOL +
+                EOL +
+                "   @Override()" + EOL +
+                "   protected void test() {}" + EOL +
+                EOL +
+                "   @Override()" + EOL +
+                "   protected void initializePage() {}" + EOL +
+                "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void invokeModifierVisitor() {
+        String code = "class A {" + EOL
+                + "  Object f() {" + EOL
+                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
+                + "}}";
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+        cu.accept(new ModifierVisitor<>(), null);
+    }
+
+    @Test
+    void handleDeprecatedAnnotationFinalClass() {
+        String code = "public final class A {}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes().forEach(type -> type.addAndGetAnnotation(Deprecated.class));
+
+        assertEquals("@Deprecated()" + EOL +
+                "public final class A {}", LexicalPreservingPrinter.print(cu));
+
+    }
+
+    @Test
+    void handleDeprecatedAnnotationAbstractClass() {
+        String code = "public abstract class A {}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getTypes().forEach(type -> type.addAndGetAnnotation(Deprecated.class));
+
+        assertEquals("@Deprecated()" + EOL +
+                "public abstract class A {}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void issue1244() {
+        String code = "public class Foo {" + EOL + EOL
+                + "// Some comment" + EOL + EOL // does work with only one \n
+                + "public void writeExternal() {}" + EOL + "}";
+        CompilationUnit originalCu = parse(code);
+        CompilationUnit cu = LexicalPreservingPrinter.setup(originalCu);
+
+        cu.findAll(ClassOrInterfaceDeclaration.class).forEach(c -> {
+            List<MethodDeclaration> methods = c.getMethodsByName("writeExternal");
+            for (MethodDeclaration method : methods) {
+                c.remove(method);
+            }
+        });
+        assertEqualsNoEol("public class Foo {\n" +
+                "// Some comment\n\n" +
+                "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    static class AddFooCallModifierVisitor extends ModifierVisitor<Void> {
+        @Override
+        public Visitable visit(MethodCallExpr n, Void arg) {
+            // Add a call to foo() on every found method call
+            return new MethodCallExpr(n, "foo");
+        }
+    }
+
+    // See issue 1277
+    @Test
+    void testInvokeModifierVisitor() {
+        String code = "class A {" + EOL +
+                "  public String message = \"hello\";" + EOL +
+                "   void bar() {" + EOL +
+                "     System.out.println(\"hello\");" + EOL +
+                "   }" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+        cu.accept(new AddFooCallModifierVisitor(), null);
+    }
+
+    static class CallModifierVisitor extends ModifierVisitor<Void> {
+        @Override
+        public Visitable visit(MethodCallExpr n, Void arg) {
+            // Add a call to foo() on every found method call
+            return new MethodCallExpr(n.clone(), "foo");
+        }
+    }
+
+    @Test
+    void invokeModifierVisitorIssue1297() {
+        String code = "class A {" + EOL +
+                "   public void bar() {" + EOL +
+                "     System.out.println(\"hello\");" + EOL +
+                "     System.out.println(\"hello\");" + EOL +
+                "     // comment" + EOL +
+                "   }" + EOL +
+                "}";
+
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+        cu.accept(new CallModifierVisitor(), null);
+    }
+
+    @Test
+    void addedBlockCommentsPrinted() {
+        String code = "public class Foo { }";
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getClassByName("Foo").get()
+                .addMethod("mymethod")
+                .setBlockComment("block");
+        assertEqualsNoEol("public class Foo {" + EOL +
+                          "    /*block*/" + EOL +
+                          "void mymethod() {" + EOL +
+                          "}" + EOL +
+                          "}", LexicalPreservingPrinter.print(cu));
+    }
+
+    @Test
+    void addedLineCommentsPrinted() {
+        String code = "public class Foo { }";
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+
+        cu.getClassByName("Foo").get()
+                .addMethod("mymethod")
+                .setLineComment("line");
+        assertEqualsNoEol("public class Foo {" + EOL +
+                          "    //line" + EOL +
+                          "void mymethod() {" + EOL +
+                          "}" + EOL +
+                          "}", LexicalPreservingPrinter.print(cu));
+    }
+    
+    @Test
+    void removedLineCommentsPrinted() {
+        String code = "public class Foo {" + EOL +
+                          "//line" + EOL +
+                          "void mymethod() {" + EOL +
+                          "}" + EOL +
+                          "}";
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+        cu.getAllContainedComments().get(0).remove();
+
+        assertEqualsNoEol("public class Foo {" + EOL +
+                          "void mymethod() {" + EOL +
+                          "}" + EOL +
+                          "}", LexicalPreservingPrinter.print(cu));        
+    }
+    
+    // Checks if comments get removed properly with Unix style line endings
+    @Test
+    void removedLineCommentsPrintedUnix() {
+        String code = "public class Foo {" + "\n" +
+                          "//line" + "\n" +
+                          "void mymethod() {" + "\n" +
+                          "}" + "\n" +
+                          "}";
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+        cu.getAllContainedComments().get(0).remove();
+        
+        assertEquals("public class Foo {" + "\n" +
+                          "void mymethod() {" + "\n" +
+                          "}" + "\n" +
+                          "}", LexicalPreservingPrinter.print(cu));        
+    }
+    
+    @Test
+    void removedBlockCommentsPrinted() {
+        String code = "public class Foo {" + EOL +
+                          "/*" + EOL +
+                          "Block comment coming through" + EOL +
+                          "*/" + EOL +
+                          "void mymethod() {" + EOL +
+                          "}" + EOL +
+                          "}";
+        CompilationUnit cu = parse(code);
+        LexicalPreservingPrinter.setup(cu);
+        cu.getAllContainedComments().get(0).remove();
+
+        assertEqualsNoEol("public class Foo {" + EOL +
+                          "void mymethod() {" + EOL +
+                          "}" + EOL +
+                          "}", LexicalPreservingPrinter.print(cu));        
+    }
+
+    @Test
+    void issue1321() {
+        CompilationUnit compilationUnit = parse("class X { X() {} private void testme() {} }");
+        LexicalPreservingPrinter.setup(compilationUnit);
+
+        ClassOrInterfaceDeclaration type = compilationUnit.getClassByName("X").get();
+        type.getConstructors().get(0).setBody(new BlockStmt().addStatement("testme();"));
+
+        assertEqualsNoEol("class X { X() {\n    testme();\n} private void testme() {} }", LexicalPreservingPrinter.print(compilationUnit));
+    }
+
+    @Test
+    void issue2001() {
+        CompilationUnit compilationUnit = parse("class X {void blubb(){X.p(\"blaubb04\");}}");
+        LexicalPreservingPrinter.setup(compilationUnit);
+
+        compilationUnit
+                .findAll(MethodCallExpr.class)
+                .forEach(Node::removeForced);
+
+        assertEqualsNoEol("class X {void blubb(){}}", LexicalPreservingPrinter.print(compilationUnit));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/TransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/TransformationsTest.java
new file mode 100644
index 0000000..f36feb3
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/TransformationsTest.java
@@ -0,0 +1,291 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.expr.NullLiteralExpr;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.ArrayType;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.type.PrimitiveType;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+import static com.github.javaparser.ast.Modifier.Keyword.STATIC;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.Utils.EOL;
+
+/**
+ * These tests are more "high level" than the ones in LexicalPreservingPrinterTest.
+ * The idea is to perform some transformations on the code, print it back and see if the generated code
+ * is the expected one. We do not care about the internal state of LexicalPreservingPrinter, just the visible result.
+ */
+class TransformationsTest extends  AbstractLexicalPreservingTest {
+
+    @Test
+    void unchangedSimpleClasses() throws IOException {
+        assertUnchanged("Example1");
+        assertUnchanged("Example2");
+    }
+
+    @Test
+    void unchangedComplexFile() throws IOException {
+        assertUnchanged("Example4");
+    }
+
+    @Test
+    void example1() throws IOException {
+        considerExample("Example1_original");
+        cu.getClassByName("A").get().getFieldByName("a").get().setModifiers(STATIC);
+        assertTransformed("Example1", cu);
+    }
+
+    @Test
+    void example2() throws IOException {
+        considerExample("Example2_original");
+        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setInitializer("10");
+        assertTransformed("Example2", cu);
+    }
+
+    @Test
+    void example3() throws IOException {
+        considerExample("Example3_original");
+        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setInitializer((Expression) null);
+        assertTransformed("Example3", cu);
+    }
+
+    @Test
+    void example5() throws IOException {
+        considerExample("Example5_original");
+        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setInitializer(new NullLiteralExpr());
+        assertTransformed("Example5", cu);
+    }
+
+    @Test
+    void example6() throws IOException {
+        considerExample("Example6_original");
+        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setName("someOtherName");
+        assertTransformed("Example6", cu);
+    }
+
+    @Test
+    void example7() throws IOException {
+        considerExample("Example7_original");
+        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setType(new ArrayType(PrimitiveType.intType()));
+        assertTransformed("Example7", cu);
+    }
+
+    @Test
+    void example8() throws IOException {
+        considerExample("Example8_original");
+        FieldDeclaration fd = cu.getClassByName("A").get().getMember(0).asFieldDeclaration();
+        fd.addVariable(new VariableDeclarator(PrimitiveType.intType(), "b"));
+        assertTransformed("Example8", cu);
+    }
+
+    @Test
+    void example9() throws IOException {
+        considerExample("Example9_original");
+        FieldDeclaration fd = cu.getClassByName("A").get().getMember(0).asFieldDeclaration();
+        fd.addVariable(new VariableDeclarator(new ArrayType(PrimitiveType.intType()), "b"));
+        assertTransformed("Example9", cu);
+    }
+
+    @Test
+    void example10() throws IOException {
+        considerExample("Example10_original");
+        cu.getClassByName("A").get().getMembers().remove(0);
+        assertTransformed("Example10", cu);
+    }
+
+    @Test
+    void exampleParam1() throws IOException {
+        considerExample("Example_param1_original");
+        MethodDeclaration md = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        md.addParameter("int", "p1");
+        assertTransformed("Example_param1", cu);
+    }
+
+    @Test
+    void exampleParam2() throws IOException {
+        considerExample("Example_param1_original");
+        MethodDeclaration md = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        md.addParameter(new ArrayType(PrimitiveType.intType()), "p1");
+        md.addParameter("char", "p2");
+        assertTransformed("Example_param2", cu);
+    }
+
+    @Test
+    void exampleParam3() throws IOException {
+        considerExample("Example_param3_original");
+        MethodDeclaration md = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        md.getParameters().remove(0);
+        assertTransformed("Example_param3", cu);
+    }
+
+    @Test
+    void exampleParam4() throws IOException {
+        considerExample("Example_param3_original");
+        MethodDeclaration md = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        md.getParameters().remove(1);
+        assertTransformed("Example_param4", cu);
+    }
+
+    @Test
+    void exampleParam5() throws IOException {
+        considerExample("Example_param3_original");
+        MethodDeclaration md = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
+        md.setType(PrimitiveType.intType());
+        assertTransformed("Example_param5b", cu);
+        md.getBody().get().getStatements().add(new ReturnStmt(new NameExpr("p1")));
+        assertTransformed("Example_param5", cu);
+    }
+
+    @Test
+    void issue2099AddingStatementAfterTraillingComment1() {
+        Statement statement = LexicalPreservingPrinter.setup(StaticJavaParser.parseStatement(
+                "    if(value != null) {" + EOL +
+                "        value.value();" + EOL +
+                "    }"));
+
+        BlockStmt blockStmt = LexicalPreservingPrinter.setup(StaticJavaParser.parseBlock("{" + EOL +
+                "       value1();" + EOL +
+                "    value2(); // Test" + EOL +
+                "}"));
+
+        blockStmt.addStatement(statement);
+        String s = LexicalPreservingPrinter.print(blockStmt);
+        String expected = "{\n" +
+                "       value1();\n" +
+                "    value2(); // Test\n" +
+                "    if(value != null) {\n" +
+                "        value.value();\n" +
+                "    }\n" +
+                "}";
+        assertEqualsNoEol(expected, s);
+    }
+
+    @Test
+    void issue2099AddingStatementAfterTraillingComment2() {
+        Statement statement = LexicalPreservingPrinter.setup(StaticJavaParser.parseStatement(
+                "    if(value != null) {" + EOL +
+                "        value.value();" + EOL +
+                "    }"));
+
+        BlockStmt blockStmt = LexicalPreservingPrinter.setup(StaticJavaParser.parseBlock("{" + EOL +
+                "       value1();" + EOL +
+                "    value2(); /* test */" + EOL +
+                "}"));
+
+        blockStmt.addStatement(statement);
+        String s = LexicalPreservingPrinter.print(blockStmt);
+        String expected = "{\n" +
+                "       value1();\n" +
+                "    value2(); /* test */\n" +
+                "    if(value != null) {\n" +
+                "        value.value();\n" +
+                "    }\n" +
+                "}";
+        assertEqualsNoEol(expected, s);
+    }
+
+
+    @Test
+    void addingStatement1() {
+        Statement statement = LexicalPreservingPrinter.setup(StaticJavaParser.parseStatement(
+                "        if(value != null) {" + EOL +
+                        "            value.value();" + EOL +
+                        "        }"));
+
+        CompilationUnit compilationUnit = LexicalPreservingPrinter.setup(StaticJavaParser.parse("public class Test {" + EOL +
+                "    public void method() {" + EOL +
+                "           value1();" + EOL +
+                "        value2(); // Test" + EOL +
+                "    }" + EOL +
+                "}"));
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration)compilationUnit.getChildNodes().get(0);
+        MethodDeclaration methodDeclaration = (MethodDeclaration)classOrInterfaceDeclaration.getChildNodes().get(2);
+        methodDeclaration.getBody().get().addStatement(statement);
+
+        String s = LexicalPreservingPrinter.print(compilationUnit);
+        String expected = "public class Test {\n" +
+                "    public void method() {\n" +
+                "           value1();\n" +
+                "        value2(); // Test\n" +
+                "        if(value != null) {\n" +
+                "            value.value();\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+        assertEqualsNoEol(expected, s);
+    }
+
+    @Test
+    void addingStatement2() {
+        Statement statement = LexicalPreservingPrinter.setup(StaticJavaParser.parseStatement(
+                "        if(value != null) {" + EOL +
+                        "            value.value();" + EOL +
+                        "        }"));
+
+        CompilationUnit compilationUnit = LexicalPreservingPrinter.setup(StaticJavaParser.parse("public class Test {" + EOL +
+                "    public void method() {" + EOL +
+                "           value1();" + EOL +
+                "        value2();" + EOL +
+                "    }" + EOL +
+                "}"));
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration)compilationUnit.getChildNodes().get(0);
+        MethodDeclaration methodDeclaration = (MethodDeclaration)classOrInterfaceDeclaration.getChildNodes().get(2);
+        methodDeclaration.getBody().get().addStatement(statement);
+
+        String s = LexicalPreservingPrinter.print(compilationUnit);
+        String expected = "public class Test {\n" +
+                "    public void method() {\n" +
+                "           value1();\n" +
+                "        value2();\n" +
+                "        if(value != null) {\n" +
+                "            value.value();\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+        assertEqualsNoEol(expected, s);
+    }
+
+    @Test
+    void addingStatement3() {
+        Statement statement = LexicalPreservingPrinter.setup(StaticJavaParser.parseStatement(
+                "        if(value != null) {" + EOL +
+                        "            value.value();" + EOL +
+                        "        }"));
+
+        CompilationUnit compilationUnit = LexicalPreservingPrinter.setup(StaticJavaParser.parse("public class Test {" + EOL +
+                "    public void method() {" + EOL +
+                "           value1();" + EOL +
+                "        value2();" + EOL + EOL +
+                "    }" + EOL +
+                "}"));
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration)compilationUnit.getChildNodes().get(0);
+        MethodDeclaration methodDeclaration = (MethodDeclaration)classOrInterfaceDeclaration.getChildNodes().get(2);
+        methodDeclaration.getBody().get().addStatement(statement);
+
+        String s = LexicalPreservingPrinter.print(compilationUnit);
+        String expected = "public class Test {\n" +
+                "    public void method() {\n" +
+                "           value1();\n" +
+                "        value2();\n" +
+                "        if(value != null) {\n" +
+                "            value.value();\n" +
+                "        }\n\n" +
+                "    }\n" +
+                "}";
+        assertEqualsNoEol(expected, s);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/ArrayCreationLevelTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/ArrayCreationLevelTransformationsTest.java
new file mode 100644
index 0000000..ef21c37
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/ArrayCreationLevelTransformationsTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast;
+
+import com.github.javaparser.ast.ArrayCreationLevel;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.ArrayCreationExpr;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.expr.NormalAnnotationExpr;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import com.github.javaparser.utils.Utils;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+/**
+ * Transforming ArrayCreationLevel and verifying the LexicalPreservation works as expected.
+ */
+class ArrayCreationLevelTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected ArrayCreationLevel consider(String code) {
+        considerExpression("new int" + code);
+        ArrayCreationExpr arrayCreationExpr = expression.asArrayCreationExpr();
+        return arrayCreationExpr.getLevels().get(0);
+    }
+
+    // Dimension
+
+    @Test
+    void addingDimension() {
+        ArrayCreationLevel it = consider("[]");
+        it.setDimension(new IntegerLiteralExpr("10"));
+        assertTransformedToString("[10]", it);
+    }
+
+    @Test
+    void removingDimension() {
+        ArrayCreationLevel it = consider("[10]");
+        it.removeDimension();
+        assertTransformedToString("[]", it);
+    }
+
+    @Test
+    void replacingDimension() {
+        ArrayCreationLevel it = consider("[10]");
+        it.setDimension(new IntegerLiteralExpr("12"));
+        assertTransformedToString("[12]", it);
+    }
+
+    // Annotations
+
+    @Test
+    void addingAnnotation() {
+        ArrayCreationLevel it = consider("[]");
+        it.addAnnotation("myAnno");
+        assertTransformedToString("@myAnno()"+ Utils.EOL+"[]", it);
+    }
+
+    @Test
+    void removingAnnotation() {
+        ArrayCreationLevel it = consider("@myAnno []");
+        it.getAnnotations().remove(0);
+        assertTransformedToString("[]", it);
+    }
+
+    @Test
+    void replacingAnnotation() {
+        ArrayCreationLevel it = consider("@myAnno []");
+        it.getAnnotations().set(0, new NormalAnnotationExpr(new Name("myOtherAnno"), new NodeList<>()));
+        assertTransformedToString("@myOtherAnno() []", it);
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/CompilationUnitTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/CompilationUnitTransformationsTest.java
new file mode 100644
index 0000000..741196d
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/CompilationUnitTransformationsTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast;
+
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static com.github.javaparser.utils.Utils.EOL;
+
+/**
+ * Transforming CompilationUnit and verifying the LexicalPreservation works as expected.
+ */
+class CompilationUnitTransformationsTest extends AbstractLexicalPreservingTest {
+
+    // packageDeclaration
+
+    @Test
+    void addingPackageDeclaration() {
+        considerCode("class A {}");
+        cu.setPackageDeclaration(new PackageDeclaration(new Name(new Name("foo"), "bar")));
+        assertTransformedToString("package foo.bar;"+ EOL + EOL + "class A {}", cu);
+    }
+
+    @Test
+    void removingPackageDeclaration() {
+        considerCode("package foo.bar; class A {}");
+        cu.removePackageDeclaration();
+        assertTransformedToString("class A {}", cu);
+    }
+
+    @Test
+    void replacingPackageDeclaration() {
+        considerCode("package foo.bar; class A {}");
+        cu.setPackageDeclaration(new PackageDeclaration(new Name(new Name("foo2"), "baz")));
+        assertTransformedToString("package foo2.baz;" +
+                EOL + EOL +
+                " class A {}", cu);
+    }
+
+    // imports
+
+    // types
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationDeclarationTransformationsTest.java
new file mode 100644
index 0000000..278b083
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationDeclarationTransformationsTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Transforming AnnotationDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class AnnotationDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    @Test
+    void unchangedExamples() throws IOException {
+        assertUnchanged("AnnotationDeclaration_Example1");
+        assertUnchanged("AnnotationDeclaration_Example3");
+        assertUnchanged("AnnotationDeclaration_Example9");
+    }
+
+    // name
+
+    @Test
+    void changingName() throws IOException {
+        considerExample("AnnotationDeclaration_Example1_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().setName("NewName");
+        assertTransformed("AnnotationDeclaration_Example1", cu);
+    }
+
+    // modifiers
+
+    @Test
+    void addingModifiers() throws IOException {
+        considerExample("AnnotationDeclaration_Example1_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().setModifiers(createModifierList(PUBLIC));
+        assertTransformed("AnnotationDeclaration_Example2", cu);
+    }
+
+    @Test
+    void removingModifiers() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().setModifiers(new NodeList<>());
+        assertTransformed("AnnotationDeclaration_Example3", cu);
+    }
+
+    @Test
+    void replacingModifiers() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().setModifiers(createModifierList(PROTECTED));
+        assertTransformed("AnnotationDeclaration_Example4", cu);
+    }
+
+    // members
+
+    @Test
+    void addingMember() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().addMember(new AnnotationMemberDeclaration(new NodeList<>(), PrimitiveType.intType(), "foo", null));
+        assertTransformed("AnnotationDeclaration_Example5", cu);
+    }
+
+    @Test
+    void removingMember() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(2).remove();
+        assertTransformed("AnnotationDeclaration_Example6", cu);
+    }
+
+    @Test
+    void replacingMember() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().setMember(2, new AnnotationMemberDeclaration(new NodeList<>(), PrimitiveType.intType(), "foo", null));
+        assertTransformed("AnnotationDeclaration_Example7", cu);
+    }
+
+    // javadoc
+
+    @Test
+    void addingJavadoc() throws IOException {
+        considerExample("AnnotationDeclaration_Example3_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().setJavadocComment("Cool this annotation!");
+        assertTransformed("AnnotationDeclaration_Example8", cu);
+    }
+
+    @Test
+    void removingJavadoc() throws IOException {
+        considerExample("AnnotationDeclaration_Example9_original");
+        boolean removed = cu.getAnnotationDeclarationByName("ClassPreamble").get().getJavadocComment().get().remove();
+        assertTrue(removed);
+        assertTransformed("AnnotationDeclaration_Example9", cu);
+    }
+
+    @Test
+    void replacingJavadoc() throws IOException {
+        considerExample("AnnotationDeclaration_Example9_original");
+        cu.getAnnotationDeclarationByName("ClassPreamble").get().setJavadocComment("Super extra cool this annotation!!!");
+        assertTransformed("AnnotationDeclaration_Example10", cu);
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationMemberDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationMemberDeclarationTransformationsTest.java
new file mode 100644
index 0000000..59121c9
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationMemberDeclarationTransformationsTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.expr.NormalAnnotationExpr;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static com.github.javaparser.utils.Utils.EOL;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Transforming AnnotationMemberDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class AnnotationMemberDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected AnnotationMemberDeclaration consider(String code) {
+        considerCode("@interface AD { " + code + " }");
+        return cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
+    }
+
+    // Name
+
+    @Test
+    void changingName() {
+        AnnotationMemberDeclaration md = consider("int foo();");
+        md.setName("bar");
+        assertTransformedToString("int bar();", md);
+    }
+
+    // Type
+
+    @Test
+    void changingType() {
+        AnnotationMemberDeclaration md = consider("int foo();");
+        md.setType("String");
+        assertTransformedToString("String foo();", md);
+    }
+
+    // Modifiers
+
+    @Test
+    void addingModifiers() {
+        AnnotationMemberDeclaration md = consider("int foo();");
+        md.setModifiers(createModifierList(PUBLIC));
+        assertTransformedToString("public int foo();", md);
+    }
+
+    @Test
+    void removingModifiers() {
+        AnnotationMemberDeclaration md = consider("public int foo();");
+        md.setModifiers(new NodeList<>());
+        assertTransformedToString("int foo();", md);
+    }
+
+    @Test
+    void replacingModifiers() {
+        AnnotationMemberDeclaration md = consider("public int foo();");
+        md.setModifiers(createModifierList(PROTECTED));
+        assertTransformedToString("protected int foo();", md);
+    }
+
+    // Default value
+
+    @Test
+    void addingDefaultValue() {
+        AnnotationMemberDeclaration md = consider("int foo();");
+        md.setDefaultValue(new IntegerLiteralExpr("10"));
+        assertTransformedToString("int foo() default 10;", md);
+    }
+
+    @Test
+    void removingDefaultValue() {
+        AnnotationMemberDeclaration md = consider("int foo() default 10;");
+        assertTrue(md.getDefaultValue().get().remove());
+        assertTransformedToString("int foo();", md);
+    }
+
+    @Test
+    void replacingDefaultValue() {
+        AnnotationMemberDeclaration md = consider("int foo() default 10;");
+        md.setDefaultValue(new IntegerLiteralExpr("11"));
+        assertTransformedToString("int foo() default 11;", md);
+    }
+
+    // Annotations
+
+    @Test
+    void addingAnnotation() {
+        AnnotationMemberDeclaration it = consider("int foo();");
+        it.addAnnotation("myAnno");
+        assertTransformedToString("@myAnno()" + EOL + "int foo();", it);
+    }
+
+    @Test
+    void addingTwoAnnotations() {
+        AnnotationMemberDeclaration it = consider("int foo();");
+        it.addAnnotation("myAnno");
+        it.addAnnotation("myAnno2");
+        assertTransformedToString("@myAnno()" + EOL + "@myAnno2()" + EOL + "int foo();", it);
+    }
+
+    @Test
+    void removingAnnotationOnSomeLine() {
+        AnnotationMemberDeclaration it = consider("@myAnno int foo();");
+        it.getAnnotations().remove(0);
+        assertTransformedToString("int foo();", it);
+    }
+
+    @Test
+    void removingAnnotationOnPrevLine() {
+        AnnotationMemberDeclaration it = consider("@myAnno" + EOL + "int foo();");
+        it.getAnnotations().remove(0);
+        assertTransformedToString("int foo();", it);
+    }
+
+    @Test
+    void replacingAnnotation() {
+        AnnotationMemberDeclaration it = consider("@myAnno int foo();");
+        it.getAnnotations().set(0, new NormalAnnotationExpr(new Name("myOtherAnno"), new NodeList<>()));
+        assertTransformedToString("@myOtherAnno() int foo();", it);
+    }
+
+    // Javadoc
+
+    @Test
+    void addingJavadoc() {
+        AnnotationMemberDeclaration it = consider("int foo();");
+        it.setJavadocComment("Cool this annotation!");
+        assertTransformedToString("@interface AD { /**Cool this annotation!*/" + EOL +
+                "int foo(); }", it.getParentNode().get());
+    }
+
+    @Test
+    void removingJavadoc() {
+        AnnotationMemberDeclaration it = consider("/**Cool this annotation!*/ int foo();");
+        assertTrue(it.getJavadocComment().get().remove());
+        assertTransformedToString("@interface AD {  int foo(); }", it.getParentNode().get());
+    }
+
+    @Test
+    void replacingJavadoc() {
+        AnnotationMemberDeclaration it = consider("/**Cool this annotation!*/ int foo();");
+        it.setJavadocComment("Super extra cool this annotation!!!");
+        assertTransformedToString("@interface AD { /**Super extra cool this annotation!!!*/ int foo(); }", it.getParentNode().get());
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ClassOrInterfaceDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ClassOrInterfaceDeclarationTransformationsTest.java
new file mode 100644
index 0000000..63d8a55
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ClassOrInterfaceDeclarationTransformationsTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static com.github.javaparser.utils.Utils.EOL;
+
+/**
+ * Transforming ClassOrInterfaceDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class ClassOrInterfaceDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected ClassOrInterfaceDeclaration consider(String code) {
+        considerCode(code);
+        return cu.getType(0).asClassOrInterfaceDeclaration();
+    }
+
+    // Name
+
+    @Test
+    void settingName() {
+        ClassOrInterfaceDeclaration cid = consider("class A {}");
+        cid.setName("B");
+        assertTransformedToString("class B {}", cid);
+    }
+
+    // isInterface
+
+    @Test
+    void classToInterface() {
+        ClassOrInterfaceDeclaration cid = consider("class A {}");
+        cid.setInterface(true);
+        assertTransformedToString("interface A {}", cid);
+    }
+
+    @Test
+    void interfaceToClass() {
+        ClassOrInterfaceDeclaration cid = consider("interface A {}");
+        cid.setInterface(false);
+        assertTransformedToString("class A {}", cid);
+    }
+
+    // typeParameters
+
+    @Test
+    void addingTypeParameterWhenThereAreNone() {
+        ClassOrInterfaceDeclaration cid = consider("class A {}");
+        cid.addTypeParameter("T");
+        assertTransformedToString("class A<T> {}", cid);
+    }
+
+    @Test
+    void addingTypeParameterAsFirstWhenThereAreSome() {
+        ClassOrInterfaceDeclaration cid = consider("class A<U> {}");
+        cid.getTypeParameters().addFirst(new TypeParameter("T", new NodeList<>()));
+        assertTransformedToString("class A<T, U> {}", cid);
+    }
+
+    @Test
+    void addingTypeParameterAsLastWhenThereAreSome() {
+        ClassOrInterfaceDeclaration cid = consider("class A<U> {}");
+        cid.addTypeParameter("T");
+        assertTransformedToString("class A<U, T> {}", cid);
+    }
+
+    // extendedTypes
+
+    @Test
+    void addingExtendedTypes() {
+        ClassOrInterfaceDeclaration cid = consider("class A {}");
+        cid.addExtendedType("Foo");
+        assertTransformedToString("class A extends Foo {}", cid);
+    }
+
+    @Test
+    void removingExtendedTypes() {
+        ClassOrInterfaceDeclaration cid = consider("public class A extends Foo {}");
+        cid.getExtendedTypes().remove(0);
+        assertTransformedToString("public class A {}", cid);
+    }
+
+    @Test
+    void replacingExtendedTypes() {
+        ClassOrInterfaceDeclaration cid = consider("public class A extends Foo {}");
+        cid.getExtendedTypes().set(0, parseClassOrInterfaceType("Bar"));
+        assertTransformedToString("public class A extends Bar {}", cid);
+    }
+
+    // implementedTypes
+
+    @Test
+    void addingImplementedTypes() {
+        ClassOrInterfaceDeclaration cid = consider("class A {}");
+        cid.addImplementedType("Foo");
+        assertTransformedToString("class A implements Foo {}", cid);
+    }
+
+    @Test
+    void removingImplementedTypes() {
+        ClassOrInterfaceDeclaration cid = consider("public class A implements Foo {}");
+        cid.getImplementedTypes().remove(0);
+        assertTransformedToString("public class A {}", cid);
+    }
+
+    @Test
+    void replacingImplementedTypes() {
+        ClassOrInterfaceDeclaration cid = consider("public class A implements Foo {}");
+        cid.getImplementedTypes().set(0, parseClassOrInterfaceType("Bar"));
+        assertTransformedToString("public class A implements Bar {}", cid);
+    }
+
+    // Modifiers
+
+    @Test
+    void addingModifiers() {
+        ClassOrInterfaceDeclaration cid = consider("class A {}");
+        cid.setModifiers(createModifierList(PUBLIC));
+        assertTransformedToString("public class A {}", cid);
+    }
+
+    @Test
+    void removingModifiers() {
+        ClassOrInterfaceDeclaration cid = consider("public class A {}");
+        cid.setModifiers(new NodeList<>());
+        assertTransformedToString("class A {}", cid);
+    }
+
+    @Test
+    void replacingModifiers() {
+        ClassOrInterfaceDeclaration cid = consider("public class A {}");
+        cid.setModifiers(createModifierList(PROTECTED));
+        assertTransformedToString("protected class A {}", cid);
+    }
+
+    // members
+
+    @Test
+    void addingField() {
+        ClassOrInterfaceDeclaration cid = consider("class A {}");
+        cid.addField("int", "foo");
+        assertTransformedToString("class A {" + EOL + "    int foo;" + EOL + "}", cid);
+    }
+
+    @Test
+    void removingField() {
+        ClassOrInterfaceDeclaration cid = consider("public class A { int foo; }");
+        cid.getMembers().remove(0);
+        assertTransformedToString("public class A {  }", cid);
+    }
+
+    @Test
+    void replacingFieldWithAnotherField() {
+        ClassOrInterfaceDeclaration cid = consider("public class A {float f;}");
+        cid.getMembers().set(0, new FieldDeclaration(new NodeList<>(), new VariableDeclarator(PrimitiveType.intType(), "bar")));
+        assertTransformedToString("public class A {int bar;}", cid);
+    }
+
+    // Annotations
+    @Test
+    void removingAnnotations() {
+        ClassOrInterfaceDeclaration cid = consider(
+                "@Value" + EOL +
+                "public class A {}");
+        cid.getAnnotationByName("Value").get().remove();
+        assertTransformedToString("public class A {}", cid);
+    }
+
+    @Test
+    void removingAnnotationsWithSpaces() {
+        ClassOrInterfaceDeclaration cid = consider(
+                  "   @Value " + EOL +
+                        "public class A {}");
+        cid.getAnnotationByName("Value").get().remove();
+        assertTransformedToString("public class A {}", cid);
+    }
+
+    // Javadoc
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ConstructorDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ConstructorDeclarationTransformationsTest.java
new file mode 100644
index 0000000..da0523f
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ConstructorDeclarationTransformationsTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.ast.type.ArrayType;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+
+/**
+ * Transforming ConstructorDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class ConstructorDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected ConstructorDeclaration consider(String code) {
+        considerCode("class A { " + code + " }");
+        return cu.getType(0).getMembers().get(0).asConstructorDeclaration();
+    }
+
+    // Name
+
+    @Test
+    void settingName() {
+        ConstructorDeclaration cd = consider("A(){}");
+        cd.setName("B");
+        assertTransformedToString("B(){}", cd);
+    }
+
+    // JavaDoc
+
+    // Modifiers
+
+    @Test
+    void addingModifiers() {
+        ConstructorDeclaration cd = consider("A(){}");
+        cd.setModifiers(createModifierList(PUBLIC));
+        assertTransformedToString("public A(){}", cd);
+    }
+
+    @Test
+    void removingModifiers() {
+        ConstructorDeclaration cd = consider("public A(){}");
+        cd.setModifiers(new NodeList<>());
+        assertTransformedToString("A(){}", cd);
+    }
+
+    @Test
+    void replacingModifiers() {
+        ConstructorDeclaration cd = consider("public A(){}");
+        cd.setModifiers(createModifierList(PROTECTED));
+        assertTransformedToString("protected A(){}", cd);
+    }
+
+    // Parameters
+
+    @Test
+    void addingParameters() {
+        ConstructorDeclaration cd = consider("A(){}");
+        cd.addParameter(PrimitiveType.doubleType(), "d");
+        assertTransformedToString("A(double d){}", cd);
+    }
+
+    @Test
+    void removingOnlyParameter() {
+        ConstructorDeclaration cd = consider("public A(double d){}");
+        cd.getParameters().remove(0);
+        assertTransformedToString("public A(){}", cd);
+    }
+
+    @Test
+    void removingFirstParameterOfMany() {
+        ConstructorDeclaration cd = consider("public A(double d, float f){}");
+        cd.getParameters().remove(0);
+        assertTransformedToString("public A(float f){}", cd);
+    }
+
+    @Test
+    void removingLastParameterOfMany() {
+        ConstructorDeclaration cd = consider("public A(double d, float f){}");
+        cd.getParameters().remove(1);
+        assertTransformedToString("public A(double d){}", cd);
+    }
+
+    @Test
+    void replacingOnlyParameter() {
+        ConstructorDeclaration cd = consider("public A(float f){}");
+        cd.getParameters().set(0, new Parameter(new ArrayType(PrimitiveType.intType()), new SimpleName("foo")));
+        assertTransformedToString("public A(int[] foo){}", cd);
+    }
+
+    // ThrownExceptions
+
+    // Body
+
+    // Annotations
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumConstantDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumConstantDeclarationTransformationsTest.java
new file mode 100644
index 0000000..31f5c15
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumConstantDeclarationTransformationsTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Transforming EnumConstantDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class EnumConstantDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected EnumConstantDeclaration consider(String code) {
+        considerCode("enum A { " + code + " }");
+        return cu.getType(0).asEnumDeclaration().getEntries().get(0);
+    }
+
+    // Name
+
+    @Test
+    void settingName() {
+        EnumConstantDeclaration ecd = consider("A");
+        ecd.setName("B");
+        assertTransformedToString("B", ecd);
+    }
+
+    // Annotations
+
+    // Javadoc
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumDeclarationTransformationsTest.java
new file mode 100644
index 0000000..c228635
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumDeclarationTransformationsTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static com.github.javaparser.utils.Utils.EOL;
+
+/**
+ * Transforming EnumDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class EnumDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected EnumDeclaration consider(String code) {
+        considerCode(code);
+        return cu.getType(0).asEnumDeclaration();
+    }
+
+    // Name
+
+    @Test
+    void settingName() {
+        EnumDeclaration cid = consider("enum A { E1, E2 }");
+        cid.setName("B");
+        assertTransformedToString("enum B { E1, E2 }", cid);
+    }
+
+    // implementedTypes
+
+    // Modifiers
+
+    @Test
+    void addingModifiers() {
+        EnumDeclaration ed = consider("enum A { E1, E2 }");
+        ed.setModifiers(createModifierList(PUBLIC));
+        assertTransformedToString("public enum A { E1, E2 }", ed);
+    }
+
+    @Test
+    void removingModifiers() {
+        EnumDeclaration ed = consider("public enum A { E1, E2 }");
+        ed.setModifiers(new NodeList<>());
+        assertTransformedToString("enum A { E1, E2 }", ed);
+    }
+
+    @Test
+    void replacingModifiers() {
+        EnumDeclaration ed = consider("public enum A { E1, E2 }");
+        ed.setModifiers(createModifierList(PROTECTED));
+        assertTransformedToString("protected enum A { E1, E2 }", ed);
+    }
+
+    @Test
+    void addingConstants() {
+        EnumDeclaration ed = consider("enum A {" + EOL +
+                " E1" + EOL +
+                "}");
+        ed.getEntries().addLast(new EnumConstantDeclaration("E2"));
+        assertTransformedToString("enum A {" + EOL +
+                " E1," + EOL +
+                " E2" + EOL +
+                "}", ed);
+    }
+
+    // members
+
+    // Annotations
+
+    // Javadoc
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/FieldDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/FieldDeclarationTransformationsTest.java
new file mode 100644
index 0000000..24d36ce
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/FieldDeclarationTransformationsTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static com.github.javaparser.utils.Utils.EOL;
+
+/**
+ * Transforming FieldDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class FieldDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected FieldDeclaration consider(String code) {
+        considerCode("class A { " + code + " }");
+        return cu.getType(0).getMembers().get(0).asFieldDeclaration();
+    }
+
+    // JavaDoc
+
+    // Modifiers
+
+    @Test
+    void addingModifiers() {
+        FieldDeclaration it = consider("int A;");
+        it.setModifiers(createModifierList(PUBLIC));
+        assertTransformedToString("public int A;", it);
+    }
+
+    @Test
+    void removingModifiers() {
+        FieldDeclaration it = consider("public int A;");
+        it.setModifiers(new NodeList<>());
+        assertTransformedToString("int A;", it);
+    }
+
+    @Test
+    void replacingModifiers() {
+        FieldDeclaration it = consider("int A;");
+        it.setModifiers(createModifierList(PROTECTED));
+        assertTransformedToString("protected int A;", it);
+    }
+
+    @Test
+    void changingTypes() {
+        FieldDeclaration it = consider("int a, b;");
+        assertTransformedToString("int a, b;", it);
+        it.getVariable(0).setType("Xyz");
+        assertTransformedToString(" a, b;", it);
+        it.getVariable(1).setType("Xyz");
+        assertTransformedToString("Xyz a, b;", it);
+    }
+
+    @Test
+    public void changingNonePrimitiveTypes() {
+        FieldDeclaration it = consider("String a;");
+        it.getVariable(0).setType("Xyz");
+    }
+
+    // Annotations
+    @Test
+    void removingAnnotations() {
+        FieldDeclaration it = consider( EOL +
+                "@Annotation" + EOL +
+                "public int A;");
+        it.getAnnotationByName("Annotation").get().remove();
+        assertTransformedToString("public int A;", it);
+    }
+
+    @Test
+    void removingAnnotationsWithSpaces() {
+        FieldDeclaration it = consider( EOL +
+                "  @Annotation " + EOL +
+                "public int A;");
+        it.getAnnotationByName("Annotation").get().remove();
+        assertTransformedToString("public int A;", it);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/InitializerDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/InitializerDeclarationTransformationsTest.java
new file mode 100644
index 0000000..8fbccb1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/InitializerDeclarationTransformationsTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.body.InitializerDeclaration;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+/**
+ * Transforming InitializerDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class InitializerDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected InitializerDeclaration consider(String code) {
+        considerCode("class A { " + code + " }");
+        return cu.getType(0).getMembers().get(0).asInitializerDeclaration();
+    }
+
+    // JavaDoc
+
+    // Body
+
+    // IsStatic
+
+    @Test
+    void instanceToStatic() {
+        InitializerDeclaration it = consider("{ /*some comment*/ }");
+        it.setStatic(true);
+        assertTransformedToString("static { /*some comment*/ }", it);
+    }
+
+    @Test
+    void staticToInstance() {
+        InitializerDeclaration it = consider("static { /*some comment*/ }");
+        it.setStatic(false);
+        assertTransformedToString("{ /*some comment*/ }", it);
+    }
+
+    // Annotations
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/MethodDeclarationTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/MethodDeclarationTransformationsTest.java
new file mode 100644
index 0000000..f9e8fa8
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/MethodDeclarationTransformationsTest.java
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2016 The JavaParser Team.
+ *
+ * This file is part of 
+ *
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
+import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.ast.expr.StringLiteralExpr;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.ArrayType;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.javadoc.Javadoc;
+import com.github.javaparser.javadoc.description.JavadocDescription;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
+import static com.github.javaparser.utils.Utils.EOL;
+
+/**
+ * Transforming MethodDeclaration and verifying the LexicalPreservation works as expected.
+ */
+class MethodDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
+
+    protected MethodDeclaration consider(String code) {
+        considerCode("class A { " + code + " }");
+        return cu.getType(0).getMembers().get(0).asMethodDeclaration();
+    }
+
+    // Name
+
+    @Test
+    void settingName() {
+        MethodDeclaration it = consider("void A(){}");
+        it.setName("B");
+        assertTransformedToString("void B(){}", it);
+    }
+
+    // JavaDoc
+
+    @Disabled
+    @Test
+    void removingDuplicateJavaDocComment() {
+        // Arrange
+        considerCode("public class MyClass {" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void oneMethod() {" + EOL +
+                "  }" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void anotherMethod() {" + EOL +
+                "  }" + EOL +
+                "}" +
+                EOL);
+
+        MethodDeclaration methodDeclaration = cu.findAll(MethodDeclaration.class).get(1);
+
+        // Act
+        methodDeclaration.removeComment();
+
+        // Assert
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("public class MyClass {\n" +
+                "\n" +
+                "  /**\n" +
+                "   * Comment A\n" +
+                "   */\n" +
+                "  public void oneMethod() {\n" +
+                "  }\n" +
+                "\n" +
+                "  public void anotherMethod() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    @Disabled
+    @Test
+    void replacingDuplicateJavaDocComment() {
+        // Arrange
+        considerCode("public class MyClass {" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void oneMethod() {" + EOL +
+                "  }" + EOL +
+                EOL +
+                "  /**" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void anotherMethod() {" + EOL +
+                "  }" + EOL +
+                "}" +
+                EOL);
+
+        MethodDeclaration methodDeclaration = cu.findAll(MethodDeclaration.class).get(1);
+
+        // Act
+        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("Change Javadoc"));
+        methodDeclaration.setJavadocComment("", javadoc);
+
+        // Assert
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("public class MyClass {\n" +
+                "\n" +
+                "  /**\n" +
+                "   * Comment A\n" +
+                "   */\n" +
+                "  public void oneMethod() {\n" +
+                "  }\n" +
+                "\n" +
+                "  /**\n" +
+                "   * Change Javadoc\n" +
+                "   */\n" +
+                "  public void anotherMethod() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    // Comments
+
+    @Disabled
+    @Test
+    void removingDuplicateComment() {
+        // Arrange
+        considerCode("public class MyClass {" + EOL +
+                EOL +
+                "  /*" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void oneMethod() {" + EOL +
+                "  }" + EOL +
+                EOL +
+                "  /*" + EOL +
+                "   * Comment A" + EOL +
+                "   */" + EOL +
+                "  public void anotherMethod() {" + EOL +
+                "  }" + EOL +
+                "}" +
+                EOL);
+
+        MethodDeclaration methodDeclaration = cu.findAll(MethodDeclaration.class).get(1);
+
+        // Act
+        methodDeclaration.removeComment();
+
+        // Assert
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("public class MyClass {\n" +
+                "\n" +
+                "  /*\n" +
+                "   * Comment A\n" +
+                "   */\n" +
+                "  public void oneMethod() {\n" +
+                "  }\n" +
+                "\n" +
+                "  public void anotherMethod() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    // Modifiers
+
+    @Test
+    void addingModifiers() {
+        MethodDeclaration it = consider("void A(){}");
+        it.setModifiers(createModifierList(PUBLIC));
+        assertTransformedToString("public void A(){}", it);
+    }
+
+    @Test
+    void removingModifiers() {
+        MethodDeclaration it = consider("public void A(){}");
+        it.setModifiers(new NodeList<>());
+        assertTransformedToString("void A(){}", it);
+    }
+
+    @Test
+    void removingModifiersWithExistingAnnotationsShort() {
+        MethodDeclaration it = consider("@Override public void A(){}");
+        it.setModifiers(new NodeList<>());
+        assertTransformedToString("@Override void A(){}", it);
+    }
+
+    @Test
+    void removingPublicModifierFromPublicStaticMethod() {
+        MethodDeclaration it = consider("public static void a(){}");
+        it.removeModifier(Modifier.Keyword.PUBLIC);
+        assertTransformedToString("static void a(){}", it);
+    }
+
+    @Test
+    void removingModifiersWithExistingAnnotations() {
+        considerCode(
+                "class X {" + EOL +
+                        "  @Test" + EOL +
+                        "  public void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).setModifiers(new NodeList<>());
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("class X {\n" +
+                "  @Test\n" +
+                "void testCase() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    @Test
+    void replacingModifiers() {
+        MethodDeclaration it = consider("public void A(){}");
+        it.setModifiers(createModifierList(PROTECTED));
+        assertTransformedToString("protected void A(){}", it);
+    }
+
+    @Test
+    void replacingModifiersWithExistingAnnotationsShort() {
+        MethodDeclaration it = consider("@Override public void A(){}");
+        it.setModifiers(createModifierList(PROTECTED));
+        assertTransformedToString("@Override protected void A(){}", it);
+    }
+
+    @Test
+    void replacingModifiersWithExistingAnnotations() {
+        considerCode(
+                "class X {" + EOL +
+                        "  @Test" + EOL +
+                        "  public void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).setModifiers(createModifierList(PROTECTED));
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("class X {\n" +
+                "  @Test\n" +
+                "  protected void testCase() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    // Parameters
+
+    @Test
+    void addingParameters() {
+        MethodDeclaration it = consider("void foo(){}");
+        it.addParameter(PrimitiveType.doubleType(), "d");
+        assertTransformedToString("void foo(double d){}", it);
+    }
+
+    @Test
+    void removingOnlyParameter() {
+        MethodDeclaration it = consider("public void foo(double d){}");
+        it.getParameters().remove(0);
+        assertTransformedToString("public void foo(){}", it);
+    }
+
+    @Test
+    void removingFirstParameterOfMany() {
+        MethodDeclaration it = consider("public void foo(double d, float f){}");
+        it.getParameters().remove(0);
+        assertTransformedToString("public void foo(float f){}", it);
+    }
+
+    @Test
+    void removingLastParameterOfMany() {
+        MethodDeclaration it = consider("public void foo(double d, float f){}");
+        it.getParameters().remove(1);
+        assertTransformedToString("public void foo(double d){}", it);
+    }
+
+    @Test
+    void replacingOnlyParameter() {
+        MethodDeclaration it = consider("public void foo(float f){}");
+        it.getParameters().set(0, new Parameter(new ArrayType(PrimitiveType.intType()), new SimpleName("foo")));
+        assertTransformedToString("public void foo(int[] foo){}", it);
+    }
+
+    // ThrownExceptions
+
+    // Body
+
+    // Annotations
+    @Test
+    void addingToExistingAnnotations() {
+        considerCode(
+                "class X {" + EOL +
+                        "  @Test" + EOL +
+                        "  public void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).addSingleMemberAnnotation(
+                "org.junit.Ignore",
+                new StringLiteralExpr("flaky test"));
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("class X {\n" +
+                "  @Test\n" +
+                "  @org.junit.Ignore(\"flaky test\")\n" +
+                "  public void testCase() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    @Test
+    void addingAnnotationsNoModifiers() {
+        considerCode(
+                "class X {" + EOL +
+                        "  void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).addMarkerAnnotation("Test");
+        cu.getType(0).getMethods().get(0).addMarkerAnnotation("Override");
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("class X {\n" +
+                "  @Test\n" +
+                "  @Override\n" +
+                "  void testCase() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    @Test
+    void replacingAnnotations() {
+        considerCode(
+                "class X {" + EOL +
+                        "  @Override" + EOL +
+                        "  public void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).setAnnotations(new NodeList<>(new MarkerAnnotationExpr("Test")));
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol(
+                "class X {\n" +
+                        "  @Test\n" +
+                        "  public void testCase() {\n" +
+                        "  }\n" +
+                        "}\n", result);
+    }
+
+    @Test
+    void addingAnnotationsShort() {
+        MethodDeclaration it = consider("void testMethod(){}");
+        it.addMarkerAnnotation("Override");
+        assertTransformedToString(
+                "@Override" + EOL +
+                        "void testMethod(){}", it);
+    }
+
+    @Test
+    void removingAnnotations() {
+        considerCode(
+                "class X {" + EOL +
+                        "  @Override" + EOL +
+                        "  public void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).getAnnotationByName("Override").get().remove();
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol(
+                "class X {\n" +
+                        "  public void testCase() {\n" +
+                        "  }\n" +
+                        "}\n", result);
+    }
+
+    @Disabled
+    @Test
+    void removingAnnotationsWithSpaces() {
+        considerCode(
+                "class X {" + EOL +
+                        "  @Override " + EOL +
+                        "  public void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).getAnnotationByName("Override").get().remove();
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol(
+                "class X {\n" +
+                        "  public void testCase() {\n" +
+                        "  }\n" +
+                        "}\n", result);
+    }
+
+    @Test
+    public void addingModifiersWithExistingAnnotationsShort() {
+        MethodDeclaration it = consider("@Override void A(){}");
+        it.setModifiers(NodeList.nodeList(Modifier.publicModifier(), Modifier.finalModifier()));
+        assertTransformedToString("@Override public final void A(){}", it);
+    }
+
+    @Test
+    public void addingModifiersWithExistingAnnotations() {
+        considerCode(
+                "class X {" + EOL +
+                        "  @Test" + EOL +
+                        "  void testCase() {" + EOL +
+                        "  }" + EOL +
+                        "}" + EOL
+        );
+
+        cu.getType(0).getMethods().get(0).addModifier(Modifier.finalModifier().getKeyword(), Modifier.publicModifier().getKeyword());
+
+        String result = LexicalPreservingPrinter.print(cu.findCompilationUnit().get());
+        assertEqualsNoEol("class X {\n" +
+                "  @Test\n" +
+                "  final public void testCase() {\n" +
+                "  }\n" +
+                "}\n", result);
+    }
+
+    @Test
+    public void parseAndPrintAnonymousClassExpression() {
+        Expression expression = parseExpression("new Object() {" + EOL +
+                "}");
+         String expected = "new Object() {" + EOL +
+                "}";
+        assertTransformedToString(expected, expression);
+    }
+
+    @Test
+    public void parseAndPrintAnonymousClassStatement() {
+        Statement statement = parseStatement("Object anonymous = new Object() {" + EOL +
+                "};");
+        String expected = "Object anonymous = new Object() {" + EOL +
+                "};";
+        assertTransformedToString(expected, statement);
+    }
+
+    @Test
+    public void replaceBodyShouldNotBreakAnonymousClasses() {
+        MethodDeclaration it = consider("public void method() { }");
+        it.getBody().ifPresent(body -> {
+            Statement statement = parseStatement("Object anonymous = new Object() {" + EOL +
+                    "};");
+            NodeList<Statement> statements = new NodeList<>();
+            statements.add(statement);
+            body.setStatements(statements);
+        });
+
+        String expected = "public void method() {" + EOL +
+                "    Object anonymous = new Object() {" + EOL +
+                "    };" + EOL +
+                "}";
+        assertTransformedToString(expected, it);
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/OperatorTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/OperatorTransformationsTest.java
new file mode 100644
index 0000000..c346bc1
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/OperatorTransformationsTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+
+/**
+ * Transforming BinaryExpr and verifying the LexicalPreservation works as expected.
+ */
+class OperatorTransformationsTest extends AbstractLexicalPreservingTest {
+
+    @Test
+    void binaryExpressionOperator() {
+        considerExpression("a && b");
+        expression.asBinaryExpr().setRight(new NameExpr("c"));
+        assertTransformedToString("a && c", expression);
+    }
+    
+    @Test
+    void unaryExpressionOperator() {
+        considerExpression("!a");
+        expression.asUnaryExpr().setExpression(new NameExpr("b"));
+        assertTransformedToString("!b", expression);
+    }
+    
+    @Test
+    void assignExpressionOperator() {
+        considerExpression("a <<= 1");
+        expression.asAssignExpr().setValue(new IntegerLiteralExpr(2));
+        assertTransformedToString("a <<= 2", expression);
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/StatementTransformationsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/StatementTransformationsTest.java
new file mode 100644
index 0000000..390fbcd
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/StatementTransformationsTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.printer.lexicalpreservation.transformations.ast.body;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
+import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+
+/**
+ * Transforming Statement and verifying the LexicalPreservation works as expected.
+ */
+class StatementTransformationsTest extends AbstractLexicalPreservingTest {
+
+    Statement consider(String code) {
+        Statement statement = parseStatement(code);
+        LexicalPreservingPrinter.setup(statement);
+        return statement;
+    }
+
+    @Test
+    void ifStmtTransformation() {
+        Statement stmt = consider("if (a) {} else {}");
+        stmt.asIfStmt().setCondition(new NameExpr("b"));
+        assertTransformedToString("if (b) {} else {}", stmt);
+    }
+
+    @Test
+    void switchEntryCsmHasTrailingUnindent() {
+        Statement stmt = consider("switch (a) { case 1: a; a; }");
+        NodeList<Statement> statements = stmt.asSwitchStmt().getEntry(0).getStatements();
+        statements.set(1, statements.get(1).clone()); // clone() to force replacement
+        assertTransformedToString("switch (a) { case 1: a; a; }", stmt);
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/remove/NodeRemovalTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/remove/NodeRemovalTest.java
new file mode 100644
index 0000000..a8eee81
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/remove/NodeRemovalTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.remove;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
+import com.github.javaparser.utils.TestParser;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+
+class NodeRemovalTest {
+	private final CompilationUnit cu = new CompilationUnit();
+
+	@Test
+	void testRemoveClassFromCompilationUnit() {
+		ClassOrInterfaceDeclaration testClass = cu.addClass("test");
+		assertEquals(1, cu.getTypes().size());
+		boolean remove = testClass.remove();
+		assertTrue(remove);
+		assertEquals(0, cu.getTypes().size());
+	}
+
+	@Test
+	void testRemoveFieldFromClass() {
+		ClassOrInterfaceDeclaration testClass = cu.addClass("test");
+
+		FieldDeclaration addField = testClass.addField(String.class, "test");
+		assertEquals(1, testClass.getMembers().size());
+		boolean remove = addField.remove();
+		assertTrue(remove);
+		assertEquals(0, testClass.getMembers().size());
+	}
+
+	@Test
+	void testRemoveStatementFromMethodBody() {
+		ClassOrInterfaceDeclaration testClass = cu.addClass("testC");
+
+		MethodDeclaration addMethod = testClass.addMethod("testM");
+		BlockStmt methodBody = addMethod.createBody();
+		Statement addStatement = methodBody.addAndGetStatement("test");
+		assertEquals(1, methodBody.getStatements().size());
+		boolean remove = addStatement.remove();
+		assertTrue(remove);
+		assertEquals(0, methodBody.getStatements().size());
+	}
+
+	@Test
+	void testRemoveStatementFromMethodBodyWithLexicalPreservingPrinter() {
+		String sample = "{\r\n" + "    log.error(\"context\", e);\r\n" +
+				"    log.error(\"context\", e);\r\n" +
+				"    throw new ApplicationException(e);\r\n" + "}\r\n";
+		BlockStmt bstmt = TestParser.parseStatement(sample).asBlockStmt();
+		BlockStmt stmt = LexicalPreservingPrinter.setup(bstmt);
+		List<Node> children = stmt.getChildNodes();
+		remove(children.get(0));
+		assertTrue(children.size() == 2);
+		remove(children.get(0));
+		assertTrue(children.size() == 1);
+		assertTrue(children.stream().allMatch(n -> n.getParentNode() != null));
+	}
+
+	// remove the node and parent's node until response is true
+	boolean remove(Node node) {
+		boolean result = node.remove();
+		if (!result && node.getParentNode().isPresent())
+			result = remove(node.getParentNode().get());
+		return result;
+	}
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/CodeGenerationUtilsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/CodeGenerationUtilsTest.java
new file mode 100644
index 0000000..d754115
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/CodeGenerationUtilsTest.java
@@ -0,0 +1,22 @@
+package com.github.javaparser.utils;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.CodeGenerationUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+class CodeGenerationUtilsTest {
+    @Test
+    void setters() {
+        assertEquals("setValue", setterName("value"));
+        assertEquals("setBlue", setterName("isBlue"));
+    }
+
+    @Test
+    void getters() {
+        assertEquals("getValue", getterName(Object.class, "value"));
+        assertEquals("isBlue", getterName(Boolean.class, "isBlue"));
+        assertEquals("isBlue", getterName(Boolean.class, "blue"));
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/LogTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/LogTest.java
new file mode 100644
index 0000000..913d296
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/LogTest.java
@@ -0,0 +1,67 @@
+package com.github.javaparser.utils;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.function.Supplier;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class LogTest {
+    private static class TestAdapter implements Log.Adapter {
+        String output = "";
+
+        @Override
+        public void info(Supplier<String> messageSupplier) {
+            output += "I" + messageSupplier.get();
+        }
+
+        @Override
+        public void trace(Supplier<String> messageSupplier) {
+            output += "T" + messageSupplier.get();
+        }
+
+        @Override
+        public void error(Supplier<Throwable> throwableSupplier, Supplier<String> messageSupplier) {
+            Throwable throwable = throwableSupplier.get();
+            String s = messageSupplier.get();
+            output += "E" + s + "M" + (throwable == null ? "null" : throwable.getMessage());
+        }
+    }
+
+    private TestAdapter testAdapter = new TestAdapter();
+
+    @BeforeEach
+    void setAdapter() {
+        Log.setAdapter(testAdapter);
+    }
+
+    @AfterEach
+    void resetAdapter() {
+        Log.setAdapter(new Log.SilentAdapter());
+    }
+
+    @Test
+    void testTrace() {
+        Log.trace("abc");
+        Log.trace("a%sc%s", () -> "b", () -> "d");
+        assertEquals("TabcTabcd", testAdapter.output);
+    }
+
+    @Test
+    void testInfo() {
+        Log.info("abc");
+        Log.info("a%sc", () -> "b");
+        assertEquals("IabcIabc", testAdapter.output);
+    }
+
+    @Test
+    void testError() {
+        Log.error("abc");
+        Log.error("a%sc", () -> "b");
+        Log.error(new Throwable("!!!"), "abc");
+        Log.error(new Throwable("!!!"), "a%sc%s", () -> "b", () -> "d");
+        assertEquals("EabcMnullEabcMnullEabcM!!!EabcdM!!!", testAdapter.output);
+    }
+}
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/PairTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/PairTest.java
new file mode 100644
index 0000000..e946614
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/PairTest.java
@@ -0,0 +1,21 @@
+package com.github.javaparser.utils;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class PairTest {
+    @Test
+    void testToString() {
+        Pair<String, String> pair = new Pair<>("abc", "def");
+
+        assertEquals("<abc, def>", pair.toString());
+    }
+
+    @Test
+    void testToStringNulls() {
+        Pair<String, String> pair = new Pair<>(null, null);
+
+        assertEquals("<null, null>", pair.toString());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/ParserCollectionStrategyTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/ParserCollectionStrategyTest.java
new file mode 100644
index 0000000..92fd749
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/ParserCollectionStrategyTest.java
@@ -0,0 +1,32 @@
+package com.github.javaparser.utils;
+
+import org.junit.jupiter.api.Test;
+
+import java.nio.file.Path;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+
+class ParserCollectionStrategyTest {
+
+    private final Path root = CodeGenerationUtils.mavenModuleRoot(ParserCollectionStrategyTest.class).resolve("").getParent();
+    private final ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root);
+
+    @Test
+    void getSourceRoots() {
+        assertFalse(projectRoot.getSourceRoots().size() == 0);
+        assertNotEquals(Optional.empty(), projectRoot.getSourceRoot(root.resolve("javaparser-core/src/main/java")));
+        assertNotEquals(Optional.empty(), projectRoot.getSourceRoot(root.resolve
+                ("javaparser-core-generators/src/main/java")));
+        assertNotEquals(Optional.empty(), projectRoot.getSourceRoot(root.resolve
+                ("javaparser-core-metamodel-generator/src/main/java")));
+        assertNotEquals(Optional.empty(), projectRoot.getSourceRoot(root.resolve
+                ("javaparser-symbol-solver-core/src/main/java")));
+        assertNotEquals(Optional.empty(), projectRoot.getSourceRoot(root.resolve
+                ("javaparser-symbol-solver-logic/src/main/java")));
+        assertNotEquals(Optional.empty(), projectRoot.getSourceRoot(root.resolve
+                ("javaparser-symbol-solver-model/src/main/java")));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java
new file mode 100644
index 0000000..551e1c0
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java
@@ -0,0 +1,70 @@
+package com.github.javaparser.utils;
+
+import com.github.javaparser.ParseProblemException;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class SourceRootTest {
+    private final Path root = CodeGenerationUtils.mavenModuleRoot(SourceRootTest.class).resolve("src/test/resources/com/github/javaparser/utils/");
+    private final SourceRoot sourceRoot = new SourceRoot(root);
+
+    @BeforeEach
+    void before() {
+        sourceRoot.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.BLEEDING_EDGE);
+    }
+
+    @Test
+    void parseTestDirectory() throws IOException {
+
+        List<ParseResult<CompilationUnit>> parseResults = sourceRoot.tryToParse();
+        List<CompilationUnit> units = sourceRoot.getCompilationUnits();
+
+        assertEquals(2, units.size());
+        assertTrue(units.stream().allMatch(unit -> !unit.getTypes().isEmpty() || unit.getModule().isPresent()));
+        assertTrue(parseResults.stream().noneMatch(cu -> cu.getResult().get().getStorage().get().getPath().toString().contains("source.root")));
+    }
+
+    @Test
+    void saveInCallback() throws IOException {
+        sourceRoot.parse("", sourceRoot.getParserConfiguration(), (localPath, absolutePath, result) -> SourceRoot.Callback.Result.SAVE);
+    }
+
+    @Test
+    void saveInCallbackParallelized() {
+        sourceRoot.parseParallelized("", sourceRoot.getParserConfiguration(), ((localPath, absolutePath, result) ->
+                SourceRoot.Callback.Result.SAVE));
+    }
+
+    @Test
+    void fileAsRootIsNotAllowed() {
+        assertThrows(IllegalArgumentException.class, () -> {
+            Path path = CodeGenerationUtils.classLoaderRoot(SourceRootTest.class).resolve("com/github/javaparser/utils/Bla.java");
+        new SourceRoot(path);
+    });
+}
+
+    @Test
+    void dotsInRootDirectoryAreAllowed() throws IOException {
+        Path path = CodeGenerationUtils.mavenModuleRoot(SourceRootTest.class).resolve("src/test/resources/com/github/javaparser/utils/source.root");
+        new SourceRoot(path).tryToParse();
+    }
+
+    @Test
+    void dotsInPackageAreNotAllowed() {
+        assertThrows(ParseProblemException.class, () -> {
+            Path path = CodeGenerationUtils.mavenModuleRoot(SourceRootTest.class).resolve("src/test/resources/com/github/javaparser/utils");
+        new SourceRoot(path).parse("source.root", "Y.java");
+    });
+}
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java
new file mode 100644
index 0000000..f5b8b71
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.utils;
+
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class SourceZipTest {
+
+    private final Path testDir = CodeGenerationUtils.mavenModuleRoot(SourceZipTest.class)
+            .resolve(Paths.get("..", "javaparser-core-testing", "src", "test", "resources", "com", "github", "javaparser",
+                    "source_zip"))
+            .normalize();
+
+    @Test
+    void parseTestDirectory() throws IOException {
+        SourceZip sourceZip = new SourceZip(testDir.resolve("test.zip"));
+        List<Pair<Path, ParseResult<CompilationUnit>>> results = sourceZip.parse();
+        assertEquals(3, results.size());
+        List<CompilationUnit> units = new ArrayList<>();
+        for (Pair<Path, ParseResult<CompilationUnit>> pr : results) {
+            units.add(pr.b.getResult().get());
+        }
+        assertTrue(units.stream().noneMatch(unit -> unit.getTypes().isEmpty()));
+    }
+
+    @Test
+    void parseTestDirectoryWithCallback() throws IOException {
+        SourceZip sourceZip = new SourceZip(testDir.resolve("test.zip"));
+        List<Pair<Path, ParseResult<CompilationUnit>>> results = new ArrayList<>();
+
+        sourceZip.parse((path, result) -> results.add(new Pair<>(path, result)));
+
+        assertEquals(3, results.size());
+        List<CompilationUnit> units = new ArrayList<>();
+        for (Pair<Path, ParseResult<CompilationUnit>> pr : results) {
+            units.add(pr.b.getResult().get());
+        }
+        assertTrue(units.stream().noneMatch(unit -> unit.getTypes().isEmpty()));
+    }
+
+    @Test
+    void dirAsZipIsNotAllowed() {
+        assertThrows(IOException.class, () -> new SourceZip(testDir.resolve("test")).parse());
+    }
+
+    @Test
+    void fileAsZipIsNotAllowed() {
+        assertThrows(IOException.class, () -> new SourceZip(testDir.resolve("test.txt")).parse());
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/TestParser.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/TestParser.java
new file mode 100644
index 0000000..cb0efd2
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/TestParser.java
@@ -0,0 +1,40 @@
+package com.github.javaparser.utils;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.Statement;
+
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.BLEEDING_EDGE;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class TestParser {
+
+    private static final JavaParser parser = new JavaParser(new ParserConfiguration().setLanguageLevel(BLEEDING_EDGE));
+
+    public static CompilationUnit parseCompilationUnit(String stmt) {
+        return unpack(parser.parse(stmt));
+    }
+
+    public static Statement parseStatement(String stmt) {
+        return unpack(parser.parseStatement(stmt));
+    }
+
+    private static <T> T unpack(ParseResult<T> result) {
+        if (!result.isSuccessful()) {
+            fail(result.getProblems().toString());
+        }
+        return result.getResult().get();
+    }
+
+    public static Expression parseExpression(String expr) {
+        return unpack(parser.parseExpression(expr));
+    }
+
+    public static BodyDeclaration<?> parseBodyDeclaration(String bd) {
+        return unpack(parser.parseBodyDeclaration(bd));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/TestUtils.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/TestUtils.java
new file mode 100644
index 0000000..571d8b6
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/TestUtils.java
@@ -0,0 +1,166 @@
+package com.github.javaparser.utils;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.expr.Expression;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+import java.io.*;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.CodeGenerationUtils.f;
+import static com.github.javaparser.utils.Utils.*;
+import static java.nio.charset.StandardCharsets.*;
+import static java.util.Arrays.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class TestUtils {
+    /**
+     * Takes care of setting all the end of line character to platform specific ones.
+     */
+    public static String readResource(String resourceName) throws IOException {
+        if (resourceName.startsWith("/")) {
+            resourceName = resourceName.substring(1);
+        }
+        try (final InputStream resourceAsStream = TestUtils.class.getClassLoader().getResourceAsStream(resourceName)) {
+            if (resourceAsStream == null) {
+                fail("not found: " + resourceName);
+            }
+            try (final InputStreamReader reader = new InputStreamReader(resourceAsStream, UTF_8);
+                 final BufferedReader br = new BufferedReader(reader)) {
+                final StringBuilder builder = new StringBuilder();
+                String line;
+                while ((line = br.readLine()) != null) {
+                    builder.append(line).append(EOL);
+                }
+                return builder.toString();
+            }
+        }
+    }
+
+    public static String readTextResource(Class<?> relativeClass, String resourceName) {
+        final URL resourceAsStream = relativeClass.getResource(resourceName);
+        try {
+            byte[] bytes = Files.readAllBytes(Paths.get(resourceAsStream.toURI()));
+            return new String(bytes, UTF_8);
+        } catch (IOException | URISyntaxException e) {
+            fail(e);
+            return null;
+        }
+    }
+
+    public static void assertInstanceOf(Class<?> expectedType, Object instance) {
+        assertTrue(expectedType.isAssignableFrom(instance.getClass()), f("%s is not an instance of %s.", instance.getClass(), expectedType));
+    }
+
+    /**
+     * Unzip a zip file into a directory.
+     */
+    public static void unzip(Path zipFile, Path outputFolder) throws IOException {
+        Log.info("Unzipping %s to %s", () -> zipFile, () -> outputFolder);
+
+        final byte[] buffer = new byte[1024 * 1024];
+
+        outputFolder.toFile().mkdirs();
+
+        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile.toFile()))) {
+            ZipEntry ze = zis.getNextEntry();
+
+            while (ze != null) {
+                final Path newFile = outputFolder.resolve(ze.getName());
+
+                if (ze.isDirectory()) {
+                    Log.trace("mkdir %s", newFile::toAbsolutePath);
+                    newFile.toFile().mkdirs();
+                } else {
+                    Log.info("unzip %s", newFile::toAbsolutePath);
+                    try (FileOutputStream fos = new FileOutputStream(newFile.toFile())) {
+                        int len;
+                        while ((len = zis.read(buffer)) > 0) {
+                            fos.write(buffer, 0, len);
+                        }
+                    }
+                }
+                zis.closeEntry();
+                ze = zis.getNextEntry();
+            }
+
+        }
+        Log.info("Unzipped %s to %s", () -> zipFile, () -> outputFolder);
+    }
+
+    /**
+     * Download a file from a URL to disk.
+     */
+    public static void download(URL url, Path destination) throws IOException {
+        OkHttpClient client = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(url)
+                .build();
+
+        Response response = client.newCall(request).execute();
+        Files.write(destination, response.body().bytes());
+    }
+
+    public static String temporaryDirectory() {
+        return System.getProperty("java.io.tmpdir");
+    }
+
+    public static void assertCollections(Collection<?> expected, Collection<?> actual) {
+        final StringBuilder out = new StringBuilder();
+        for (Object e : expected) {
+            if (actual.contains(e)) {
+                actual.remove(e);
+            } else {
+                out.append("Missing: ").append(e).append(EOL);
+            }
+        }
+        for (Object a : actual) {
+            out.append("Unexpected: ").append(a).append(EOL);
+        }
+
+        String s = out.toString();
+        if (s.isEmpty()) {
+            return;
+        }
+        fail(s);
+    }
+
+    public static void assertProblems(ParseResult<?> result, String... expectedArg) {
+        assertProblems(result.getProblems(), expectedArg);
+    }
+
+    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<>(asList(expectedArg));
+        assertCollections(expected, actual);
+    }
+
+    public static void assertNoProblems(ParseResult<?> result) {
+        assertProblems(result);
+    }
+
+    public static void assertExpressionValid(String expression) {
+        JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
+        ParseResult<Expression> result = javaParser.parse(ParseStart.EXPRESSION, provider(expression));
+        assertTrue(result.isSuccessful(), result.getProblems().toString());
+    }
+
+    /**
+     * Assert that "actual" equals "expected", and that any EOL characters in "actual" are correct for the platform.
+     */
+    public static void assertEqualsNoEol(String expected, String actual) {
+        assertEquals(normalizeEolInTextBlock(expected, EOL), actual);
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/UtilsTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/UtilsTest.java
new file mode 100644
index 0000000..4377571
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/UtilsTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.utils;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Optional;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.utils.Utils.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class UtilsTest {
+
+    @Test
+    public void testIsNullOrEmpty() {
+        assertTrue(isNullOrEmpty(null));
+        assertTrue(isNullOrEmpty(new ArrayList<>()));
+
+        assertFalse(isNullOrEmpty(
+                new ArrayList<>(Arrays.asList("foo", "bar"))));
+    }
+
+    @Test
+    public void testAssertNotNull() {
+        assertEquals("foo", assertNotNull("foo"));
+        assertThrows(AssertionError.class, () -> assertNotNull(null));
+    }
+
+    @Test
+    public void testAssertNonEmpty() {
+        assertEquals("foo", assertNonEmpty("foo"));
+        assertThrows(AssertionError.class, () -> assertNonEmpty(""));
+        assertThrows(AssertionError.class, () -> assertNonEmpty(null));
+
+    }
+
+    @Test
+    public void testAssertNonNegative() {
+        assertEquals((Number) 2, assertNonNegative(2));
+        assertThrows(AssertionError.class, () -> assertNonNegative(-2));
+    }
+
+    @Test
+    public void testAssertPositive() {
+        assertEquals((Number) 2, assertPositive(2));
+        assertThrows(AssertionError.class, () -> assertPositive(-2));
+    }
+
+    @Test
+    public void testEscapeEndOfLines() {
+        assertEquals("f\\no\\ro", escapeEndOfLines("f\no\ro"));
+    }
+
+    @Test
+    public void testReaderToString() throws IOException {
+        Reader reader = new Reader() {
+            @Override
+            public int read(char[] chars, int i, int i1) throws IOException {
+                return 0;
+            }
+
+            @Override
+            public void close() throws IOException {
+            }
+        };
+        assertEquals("", readerToString(reader));
+    }
+
+    @Test
+    public void testToCamelCase() {
+        assertEquals("foo", toCamelCase("foo"));
+        assertEquals("foo", toCamelCase("Foo"));
+        assertEquals("foo", toCamelCase("FOO"));
+        assertEquals("foo", toCamelCase("fOo"));
+    }
+
+    @Test
+    void testScreamingToCamelCase() {
+        assertEquals("abc", screamingToCamelCase("ABC"));
+        assertEquals("abcDef", screamingToCamelCase("ABC_DEF"));
+        assertEquals("abc", screamingToCamelCase("ABC_"));
+    }
+
+    @Test
+    void screamingEmptyString() {
+        assertEquals("", camelCaseToScreaming(""));
+        assertEquals("ABC", camelCaseToScreaming("abc"));
+        assertEquals("HELLO_HELLO", camelCaseToScreaming("HelloHello"));
+        assertEquals("APE_TAIL", camelCaseToScreaming("apeTail"));
+    }
+
+    @Test
+    public void testNextWord() {
+        assertEquals("foo", nextWord("foo"));
+        assertEquals("foo", nextWord("foo bar"));
+        assertEquals("foo", nextWord("foo bar Baz"));
+    }
+
+    @Test
+    public void testIndent() {
+        assertEquals("foo",
+                indent(new StringBuilder("foo"), 0).toString());
+        assertEquals("foo\t",
+                indent(new StringBuilder("foo"), 1).toString());
+        assertEquals("foo\t\t",
+                indent(new StringBuilder("foo"), 2).toString());
+        assertEquals("foo\t\t\t",
+                indent(new StringBuilder("foo"), 3).toString());
+    }
+
+    @Test
+    void capitalizeOnEmptyString() {
+        assertThrows(IllegalArgumentException.class, () -> capitalize(""));
+    }
+
+    @Test
+    void capitalizeOnStringOfOneCharacter() {
+        assertEquals("F", capitalize("f"));
+    }
+
+    @Test
+    void capitalizeOnStringOfTwoCharacters() {
+        assertEquals("Fo", capitalize("fo"));
+    }
+
+    @Test
+    void decapitalizeOnEmptyString() {
+        assertThrows(IllegalArgumentException.class, () -> decapitalize(""));
+    }
+
+    @Test
+    void decapitalizeOnStringOfOneCharacter() {
+        assertEquals("f", decapitalize("F"));
+    }
+
+    @Test
+    void decapitalizeOnStringOfTwoCharacters() {
+        assertEquals("fo", decapitalize("Fo"));
+    }
+
+    @Test
+    public void testValueIsNullOrEmpty() {
+        assertTrue(valueIsNullOrEmpty(null));
+        assertTrue(valueIsNullOrEmpty(Optional.empty()));
+        assertTrue(valueIsNullOrEmpty(new ArrayList<>()));
+
+        assertFalse(valueIsNullOrEmpty(
+                Optional.ofNullable("foo")));
+        assertFalse(valueIsNullOrEmpty(
+                new ArrayList<>(Arrays.asList("foo", "bar"))));
+    }
+
+    @Test
+    public void testValueIsNullOrEmptyStringOrOptional() {
+        assertTrue(valueIsNullOrEmptyStringOrOptional(null));
+        assertTrue(valueIsNullOrEmptyStringOrOptional(
+                Optional.empty()));
+
+        assertFalse(valueIsNullOrEmptyStringOrOptional("foo"));
+        assertFalse(valueIsNullOrEmptyStringOrOptional(
+                Optional.ofNullable("foo")));
+    }
+
+    @Test
+    public void testIndexOfElementByObjectIdentity() {
+        assertEquals(-1, indexOfElementByObjectIdentity(
+                new ArrayList<>(), "bar"));
+        assertEquals(1, indexOfElementByObjectIdentity(
+                new ArrayList<>(Arrays.asList("foo", "bar")), "bar"));
+    }
+
+    @Test
+    public void testSet() {
+        assertEquals(new HashSet<>(Arrays.asList("bar", "foo", "baz")),
+                set("foo", "bar", "baz"));
+    }
+
+    @Test
+    void normalizeEolInTextBlock() {
+        String result = Utils.normalizeEolInTextBlock("\r\n \r \n", "Q");
+        assertEquals("Q Q Q", result);
+    }
+
+    @Test
+    public void testRemoveFileExtension() {
+        assertEquals("foo", removeFileExtension("foo"));
+        assertEquals("foo", removeFileExtension("foo.txt"));
+    }
+
+    @Test
+    void testTrimTrailingSpaces() {
+        assertEquals("abc", trimTrailingSpaces("abc"));
+        assertEquals("  abc", trimTrailingSpaces("  abc"));
+        assertEquals("abc", trimTrailingSpaces("abc  "));
+        assertEquals("  abc", trimTrailingSpaces("  abc  "));
+        assertEquals("abc", trimTrailingSpaces("abc\t\0"));
+        assertEquals("", trimTrailingSpaces("    "));
+        assertEquals("", trimTrailingSpaces(""));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorListTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorListTest.java
new file mode 100644
index 0000000..91f3afc
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorListTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.utils;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.visitor.ObjectIdentityEqualsVisitor;
+import com.github.javaparser.ast.visitor.ObjectIdentityHashCodeVisitor;
+
+class VisitorListTest {
+
+    @Test
+    void visitorAddAll() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        vList.addAll(list);
+        for (int i = 0; i < list.size(); i++)
+            assertEquals(list.get(i), vList.get(i));
+    }
+
+    @Test
+    void visitorAddAllAtIndex() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class Y{}"));
+        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        vList.add(parse("class A{}"));
+        vList.add(parse("class B{}"));
+        vList.addAll(2, list);
+        vList.add(parse("class C{}"));
+        for (int i = 0; i < list.size(); i++)
+            assertEquals(list.get(i), vList.get(2 + i));
+    }
+
+    @Test
+    void visitorListContains() {
+        CompilationUnit x1 = parse("class X{}");
+        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        list.add(x1);
+        assertTrue(list.contains(x1));
+    }
+
+    @Test
+    void visitorListContainsAll() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        vList.addAll(list);
+        assertTrue(vList.size() == 2 && vList.containsAll(list));
+    }
+
+    @Test
+    void visitorListIterator() {
+        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        CompilationUnit x1 = parse("class X{}");
+        list.add(x1);
+        CompilationUnit x2 = parse("class X{}");
+        list.add(x2);
+        Iterator<CompilationUnit> itr = list.iterator();
+        assertEquals(x1, itr.next());
+        itr.remove();
+        assertEquals(1, list.size());
+        assertEquals(x2, itr.next());
+        itr.remove();
+        assertEquals(0, list.size());
+    }
+
+    @Test
+    void visitorListListIterator() {
+        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        CompilationUnit x1 = parse("class X{}");
+        list.add(x1);
+        CompilationUnit x2 = parse("class X{}");
+        list.add(x2);
+        Iterator<CompilationUnit> itr = list.listIterator(2);
+        assertEquals(x1, itr.next());
+        itr.remove();
+        assertEquals(3, list.size());
+        assertEquals(x2, itr.next());
+        itr.remove();
+        assertEquals(2, list.size());
+    }
+
+    @Test
+    void visitorListRemove() {
+        CompilationUnit x1 = parse("class X{}");
+        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        list.add(x1);
+        assertTrue(list.remove(x1));
+    }
+
+    @Test
+    void visitorListRemoveAll() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        vList.addAll(list);
+        vList.removeAll(list);
+        assertEquals(0, vList.size());
+    }
+
+    @Test
+    void visitorListRetainAll() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        vList.addAll(list);
+        vList.add(parse("class X{}"));
+        vList.retainAll(list);
+        assertEquals(2, vList.size());
+    }
+
+    @Test
+    void visitorListSubList() {
+        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        assertEquals(4, list.size());
+        List<CompilationUnit> subLst = list.subList(1, 3);
+        assertEquals(2, subLst.size());
+        subLst.add(parse("class X{}"));
+        assertEquals(3, subLst.size());
+        assertEquals(5, list.size());
+
+    }
+
+    @Test
+    void visitorListToArray() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        List<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        vList.addAll(list);
+        for (CompilationUnit u : vList.toArray(new CompilationUnit[2]))
+            assertTrue(vList.contains(u));
+    }
+
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorMapTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorMapTest.java
new file mode 100644
index 0000000..8560e1a
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorMapTest.java
@@ -0,0 +1,80 @@
+package com.github.javaparser.utils;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.visitor.ObjectIdentityEqualsVisitor;
+import com.github.javaparser.ast.visitor.ObjectIdentityHashCodeVisitor;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class VisitorMapTest {
+    @Test
+    void normalEqualsDoesDeepCompare() {
+        CompilationUnit x1 = parse("class X{}");
+        CompilationUnit x2 = parse("class X{}");
+
+        Map<CompilationUnit, Integer> map = new HashMap<>();
+        map.put(x1, 1);
+        map.put(x2, 2);
+        assertEquals(1, map.size());
+    }
+
+    @Test
+    void objectIdentityEqualsDoesShallowCompare() {
+        CompilationUnit x1 = parse("class X{}");
+        CompilationUnit x2 = parse("class X{}");
+
+        Map<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
+        map.put(x1, 1);
+        map.put(x2, 2);
+        assertEquals(2, map.size());
+    }
+    
+    @Test
+    void visitorMapGet(){
+    	CompilationUnit x1 = parse("class X{}");
+
+        Map<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
+        map.put(x1, 1);
+        assertEquals(1, (int)map.get(x1));
+    }
+    
+    @Test
+    void visitorMapContainsKey(){
+    	CompilationUnit x1 = parse("class X{}");
+
+        Map<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
+        map.put(x1, 1);
+        assertTrue(map.containsKey(x1));
+    }
+    
+    @Test
+    void visitorMapPutAll(){
+    	CompilationUnit x1 = parse("class X{}");
+    	CompilationUnit x2 = parse("class Y{}");
+    	Map<CompilationUnit, Integer> map = new HashMap<>();
+    	map.put(x1, 1);
+    	map.put(x2, 2);
+    	Map<CompilationUnit, Integer> visitorMap = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
+        visitorMap.putAll(map);
+        assertEquals(2, visitorMap.size());
+    }
+    
+    @Test
+    void remove(){
+        CompilationUnit x1 = parse("class X{}");
+        VisitorMap<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
+        map.put(x1, 1);
+        assertTrue(map.containsKey(x1));
+        
+        map.remove(x1);
+        
+        assertFalse(map.containsKey(x1));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorSetTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorSetTest.java
new file mode 100644
index 0000000..8054c4d
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/utils/VisitorSetTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.utils;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.jupiter.api.Test;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.visitor.ObjectIdentityEqualsVisitor;
+import com.github.javaparser.ast.visitor.ObjectIdentityHashCodeVisitor;
+
+class VisitorSetTest {
+
+    @Test
+    void normalEqualsDoesDeepCompare() {
+        Set<CompilationUnit> set = new HashSet<>();
+        set.add(parse("class X{}"));
+        set.add(parse("class X{}"));
+        assertEquals(1, set.size());
+    }
+
+    @Test
+    void objectIdentityEqualsDoesShallowCompare() {
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        set.add(parse("class X{}"));
+        set.add(parse("class X{}"));
+        assertEquals(2, set.size());
+    }
+
+    @Test
+    void visitorSetContains() {
+        CompilationUnit x1 = parse("class X{}");
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        set.add(x1);
+        assertTrue(set.contains(x1));
+    }
+
+    @Test
+    void visitorSetContainsAll() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        set.addAll(list);
+        assertTrue(set.size() == 2 && set.containsAll(list));
+    }
+
+    @Test
+    void visitorSetIterator() {
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        CompilationUnit x1 = parse("class X{}");
+        set.add(x1);
+        CompilationUnit x2 = parse("class X{}");
+        set.add(x2);
+        Iterator<CompilationUnit> itr = set.iterator();
+        assertEquals(x1, itr.next());
+        itr.remove();
+        assertEquals(1, set.size());
+        assertEquals(x2, itr.next());
+        itr.remove();
+        assertEquals(0, set.size());
+    }
+
+    @Test
+    void visitorSetRemove() {
+        CompilationUnit x1 = parse("class X{}");
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        set.add(x1);
+        assertTrue(set.remove(x1));
+    }
+
+    @Test
+    void visitorSetRemoveAll() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        set.addAll(list);
+        set.removeAll(list);
+        assertEquals(0, set.size());
+    }
+
+    @Test
+    void visitorSetRetainAll() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        set.addAll(list);
+        set.add(parse("class X{}"));
+        set.retainAll(list);
+        assertEquals(2, set.size());
+    }
+
+    @Test
+    void visitorSetToArray() {
+        List<CompilationUnit> list = new ArrayList<>();
+        list.add(parse("class X{}"));
+        list.add(parse("class X{}"));
+        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
+                new ObjectIdentityEqualsVisitor());
+        set.addAll(list);
+        for (CompilationUnit u : set.toArray(new CompilationUnit[2]))
+            assertTrue(set.contains(u));
+    }
+}
diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/version/Java10PostProcessorTest.java b/javaparser-core-testing/src/test/java/com/github/javaparser/version/Java10PostProcessorTest.java
new file mode 100644
index 0000000..0e0bff9
--- /dev/null
+++ b/javaparser-core-testing/src/test/java/com/github/javaparser/version/Java10PostProcessorTest.java
@@ -0,0 +1,28 @@
+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.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.github.javaparser.ParseStart.STATEMENT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_10;
+import static com.github.javaparser.Providers.provider;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Java10PostProcessorTest {
+    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_10));
+
+    @Test
+    void varIsAType() {
+        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var x=\"\";"));
+
+        List<VarType> allVarTypes = result.getResult().get().findAll(VarType.class);
+
+        assertEquals(1, allVarTypes.size());
+    }
+}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/TestFileIso88591.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/TestFileIso88591.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/TestFileIso88591.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/TestFileIso88591.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_generators_src_main_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_generators_src_main_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_metamodel_generator_src_main_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_metamodel_generator_src_main_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_src_main_java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_src_main_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_testing_src_test_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_core_testing_src_test_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_metamodel_generator_src_main_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_metamodel_generator_src_main_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_core_src_main_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_core_src_main_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_logic_src_main_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_logic_src_main_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_model_src_main_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_model_src_main_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_testing_src_test_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_symbol_solver_testing_src_test_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_testing_src_test_java.txt
similarity index 100%
copy from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results.txt
copy to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/javaparser_test_results_javaparser_testing_src_test_java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_repo_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_repo_test_results.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_repo_test_results.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_repo_test_results.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_zip_test_results.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_zip_test_results.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_zip_test_results.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/bulk_test_results/openjdk_src_zip_test_results.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/issue_samples/Issue290.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/issue_samples/Issue290.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/issue_samples/Issue290.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/issue_samples/Issue290.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/issue_samples/Issue624.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/issue_samples/Issue624.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/issue_samples/Issue624.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/issue_samples/Issue624.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/issue_samples/issue1003.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/issue_samples/issue1003.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/issue_samples/issue1003.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/issue_samples/issue1003.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step1.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step1.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step1.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step1.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step2.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step2.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step2.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step2.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step3.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step3.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step3.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step3.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step4.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step4.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step4.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/ASimpleClassWithMoreFormatting_step4.java.txt
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example10_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example10_expected.java.txt
new file mode 100644
index 0000000..e500927
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example10_expected.java.txt
@@ -0,0 +1,11 @@
+// some example
+/**Super extra cool this annotation!!!*/
+public @interface ClassPreamble {
+   String author();
+   String date();
+   int currentRevision() default 1;
+   String lastModified() default "N/A";
+   String lastModifiedBy() default "N/A";
+   // Note use of array
+   String[] reviewers();
+}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example1_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example2_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example2_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example2_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example2_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example3_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example4_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example4_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example4_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example4_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example5_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example5_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example5_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example5_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example6_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example6_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example6_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example6_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example7_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example7_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example7_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example7_expected.java.txt
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example8_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example8_expected.java.txt
new file mode 100644
index 0000000..d3052f4
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example8_expected.java.txt
@@ -0,0 +1,12 @@
+// some example
+
+/**Cool this annotation!*/
+public @interface ClassPreamble {
+   String author();
+   String date();
+   int currentRevision() default 1;
+   String lastModified() default "N/A";
+   String lastModifiedBy() default "N/A";
+   // Note use of array
+   String[] reviewers();
+}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example9_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example10_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example1_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example2_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example3_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example4_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example4_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example4_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example4_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example5_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example6_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example7_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example8_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example9_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param1_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param2_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param2_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param2_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param2_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_original.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_original.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_original.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param3_original.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param4_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param4_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param4_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param4_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5b_expected.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5b_expected.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5b_expected.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/Example_param5b_expected.java.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/MethodWithOneStatement.java.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/MethodWithOneStatement.java.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/MethodWithOneStatement.java.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/MethodWithOneStatement.java.txt
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/JavaConcepts_prettyprinted b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/JavaConcepts_prettyprinted
new file mode 100644
index 0000000..e180a08
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/JavaConcepts_prettyprinted
@@ -0,0 +1,398 @@
+package japa.bdd.samples;
+
+import com.github.javaparser.JavaParser;
+import japa.parser.ParseException;
+import com.github.javaparser.ast.CompilationUnit;
+import org.junit.Ignore;
+import java.io.*;
+import java.util.*;
+
+@Ignore
+@Deprecated
+public class JavaConcepts<T extends List<int[]>, X> extends Base implements Serializable {
+
+    static Class clz1 = String.class;
+
+    protected Class clz2 = (String.class);
+
+    Class clz3 = int.class;
+
+    Class clz4 = (int.class);
+
+    int[] arr = new int[10];
+
+    byte bye = 0;
+
+    byte[] byebye = null;
+
+    short sh1, sh2 = 1;
+
+    int intWithUnderscore = 1234_5678;
+
+    long longWithUnderscore = 1234_5678L;
+
+    float floatWithUnderscore = 1_234.5_678f;
+
+    float floatWithUnderscoreAndExponent = 1_234e1_0f;
+
+    double doubleWithUnderscore = 1_234.5_678;
+
+    double doubleWithUnderscoreAndExponent = 1_234e1_0;
+
+    int binaryLiteral = 0b101101;
+
+    List<String>[][] arrLS = (List<String>[][]) new List<?>[10][];
+
+    {
+        int z = 0, y = 0;
+        int a = (z) + y;
+        a = (+z) + y;
+        byte b = (byte) +y;
+    }
+
+    List<String> diamond1 = new LinkedList<>();
+
+    @Deprecated()
+    static class Ugly {
+
+        static int x = 0;
+
+        public static void main(String[] args) {
+            x = +x;
+            x = ~x;
+            --x;
+            boolean b = !false;
+            x &= 2;
+            x |= 2;
+            x ^= 2;
+            x -= 2;
+            x %= 2;
+            x /= 2;
+            x *= 2;
+            x <<= 2;
+            x >>= 2;
+            x >>>= 2;
+            b = b || false;
+            b = b | false;
+            b = b & false;
+            b = b ^ false;
+            b = b != false;
+            b = x > 1;
+            b = x < 1;
+            b = x >= 1;
+            b = x <= 1;
+            x = x << 1;
+            x = x >> 1;
+            x = x >>> 1;
+            x = x - 1;
+            x = x * 1;
+            x = x % 1;
+            x = x / 1;
+        }
+    }
+
+    @Deprecated()
+    int[][][][] arr2 = new int[10][2][1][0];
+
+    volatile float fff = 0x1.fffeP+127f;
+
+    char cc = 'a';
+
+    int[][] arr3 = { { 1, 2 }, { 3, 4 } };
+
+    static int[][] arr4 = {};
+
+    public static JavaConcepts t;
+
+    static {
+        arr4 = new int[][] { { 2 }, { 1 } };
+    }
+
+    {
+        arr3 = new int[][] { { 2 }, { 1 } };
+    }
+
+    public enum Teste {
+
+        asc,
+        def
+    }
+
+    public enum Sexo {
+
+        m,
+        @Deprecated
+        f;
+
+        public enum Sexo_ implements Serializable, Cloneable {
+
+        }
+
+        private Sexo() {
+        }
+    }
+
+    @Deprecated
+    public enum Enum {
+
+        m(1) {
+
+            @Override
+            void mm() {
+            }
+        }
+        ,
+        f(2) {
+
+            void mm() {
+            }
+        }
+        ;
+
+        native void nnn();
+
+        transient int x;
+
+        private Enum(int x) {
+            this.x = x;
+        }
+
+        abstract void mm();
+    }
+
+    strictfp double ddd() {
+        return 0.0;
+    }
+
+    public <T, E> JavaConcepts(int x) {
+        this.arr[0] = x;
+        T val1 = null;
+        E val2 = null;
+        super.<T, E>check2(val1, val2);
+        boolean b = true, y = false;
+        abstract class X {
+
+            int i = 0;
+
+            public <D> X() {
+            }
+
+            public void m() {
+            }
+        }
+        @Deprecated
+        final class Y extends X {
+
+            public Y() {
+                super();
+                JavaConcepts.this.cc = 'c';
+                super.i = 1;
+                Y.super.m();
+            }
+
+            public Y(int y) {
+                super();
+            }
+
+            public Y(long x) {
+                this();
+            }
+        }
+    }
+
+    public <T> JavaConcepts(String str) {
+    }
+
+    private class QWE extends JavaConcepts<List<int[]>, String> {
+
+        @Deprecated
+        final int z = 0;
+
+        int i = (int) -1;
+
+        public QWE(String... x) {
+            <String>super(x[0]);
+        }
+
+        public QWE(int... x) {
+            super(x[0]);
+            i = x[0];
+            assert true;
+            assert 1 == 1 : 2;
+            {
+                int iii = 3;
+                iii += 3;
+            }
+            label: {
+                int iii = 1;
+            }
+            ;
+            ;
+            int min = -2147483648;
+            long sl = 123123123123l;
+            long minl = -9223372036854775808L;
+            switch(i) {
+            }
+            ll: switch(i) {
+                case 1:
+                    System.out.println(1);
+                    break ll;
+                default:
+                    {
+                        System.out.println("default");
+                        break;
+                    }
+                case 2:
+                    if (t instanceof Base) {
+                        System.out.println(1);
+                    }
+                    i++;
+                    ++i;
+            }
+        }
+
+        private synchronized int[] doSomething() {
+            List<? extends Number> x = new ArrayList<Integer>();
+            return new int[] { 1 };
+        }
+    }
+
+    public static void main(String[] args) throws ParseException, IOException {
+        int x = 2;
+        CompilationUnit cu = parse(new File("src/japa/parser/javacc/Parser.java"));
+        System.out.println(cu);
+        JavaConcepts teste = new JavaConcepts(2);
+        JavaConcepts.QWE qwe = teste.new QWE(1);
+        if (1 + 1 == 2) {
+            teste = null;
+            teste = new JavaConcepts(1);
+        } else {
+            x = 3;
+            teste = new JavaConcepts(1);
+            x = x == 0 ? 2 : 4;
+        }
+        if (true)
+            x = 1;
+        else
+            x = 3;
+        if (true)
+            x = 1;
+        else if (false)
+            x = 3;
+        else
+            x = 2;
+        while (true) {
+            xxx: while (x == 3) continue xxx;
+            break;
+        }
+        do {
+            x++;
+        } while (x < 100);
+        do x++; while (x < 100);
+        for (@Deprecated int i : arr4[0]) {
+            x--;
+        }
+        for (@Deprecated final int i = 0, j = 1; i < 10; x++) {
+            break;
+        }
+        int i, j;
+        for (i = 0, j = 1; i < 10 && j < 2; i++, j--) {
+            break;
+        }
+    }
+
+    public static CompilationUnit parse(@Deprecated File file) throws ParseException, IOException {
+        String a = ((String) "qwe");
+        String x = ((String) clz1.getName());
+        int y = ((Integer) (Object) x).intValue();
+        synchronized (file) {
+            file = null;
+            file = new File("");
+        }
+        try {
+            if (file == null) {
+                throw new NullPointerException("blah");
+            }
+        } catch (final NullPointerException e) {
+            System.out.println("catch");
+        } catch (RuntimeException e) {
+            System.out.println("catch");
+        } finally {
+            System.out.println("finally");
+        }
+        try {
+            if (file == null) {
+                throw new NullPointerException("blah");
+            }
+        } finally {
+            System.out.println("finally");
+        }
+        try {
+            if (file == null) {
+                throw new NullPointerException("blah");
+            }
+        } catch (RuntimeException e) {
+            System.out.println("catch");
+        }
+        try (InputStream in = createInputStream()) {
+            System.out.println(in);
+        } catch (IOException e) {
+            System.out.println("catch");
+        }
+        try (InputStream in = createInputStream();
+            InputStream in2 = createInputStream()) {
+            System.out.println(in);
+        } catch (IOException e) {
+            System.out.println("catch");
+        }
+        try (InputStream in = createInputStream()) {
+            System.out.println(in);
+        }
+        try {
+            System.out.println("whatever");
+        } catch (RuntimeException e) {
+            System.out.println(e);
+        } catch (final Exception | Error e) {
+            System.out.println(e);
+        }
+        return JavaParser.parse(file);
+    }
+
+    class A<T extends Integer & Serializable> implements XXX, Serializable {
+
+        public <ABC> A(Integer integer, ABC string) throws Exception, IOException {
+        }
+    }
+
+    private <Y> void x(Map<? extends X, ? super T> x) {
+        @Deprecated Comparator c = new Comparator() {
+
+            public int compare(Object o1, Object o2) {
+                try {
+                    A<Integer> a = new <String> A<Integer>(new Integer(11), "foo") {
+                    };
+                } catch (Exception e) {
+                }
+                return 0;
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                return super.equals(obj);
+            }
+        };
+    }
+
+    private static InputStream createInputStream() {
+        return new ByteArrayInputStream(null);
+    }
+}
+
+class Base {
+
+    public <A, B> void check2(A val1, B val2) {
+    }
+}
+
+interface XXX extends Serializable, Cloneable {
+}
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/PrettyPrintVisitor_prettyprinted b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/PrettyPrintVisitor_prettyprinted
new file mode 100644
index 0000000..37e9580
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/PrettyPrintVisitor_prettyprinted
@@ -0,0 +1,1353 @@
+/*
+ * 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.printer;
+
+import com.github.javaparser.ast.*;
+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.nodeTypes.NodeWithTypeArguments;
+import com.github.javaparser.ast.nodeTypes.NodeWithVariables;
+import com.github.javaparser.ast.stmt.*;
+import com.github.javaparser.ast.type.*;
+import com.github.javaparser.ast.visitor.VoidVisitor;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition;
+import static com.github.javaparser.utils.Utils.isNullOrEmpty;
+
+/**
+ * Outputs the AST as formatted Java source code.
+ *
+ * @author Julio Vilmar Gesser
+ */
+public class PrettyPrintVisitor implements VoidVisitor<Void> {
+
+    protected final PrettyPrinterConfiguration configuration;
+
+    protected final SourcePrinter printer;
+
+    public PrettyPrintVisitor(PrettyPrinterConfiguration prettyPrinterConfiguration) {
+        configuration = prettyPrinterConfiguration;
+        printer = new SourcePrinter(configuration.getIndent());
+    }
+
+    public String getSource() {
+        return printer.getSource();
+    }
+
+    private void printModifiers(final EnumSet<Modifier> modifiers) {
+        if (modifiers.size() > 0) {
+            printer.print(modifiers.stream().map(Modifier::asString).collect(Collectors.joining(" ")) + " ");
+        }
+    }
+
+    private void printMembers(final NodeList<BodyDeclaration<?>> members, final Void arg) {
+        for (final BodyDeclaration<?> member : members) {
+            printer.println();
+            member.accept(this, arg);
+            printer.println();
+        }
+    }
+
+    private void printMemberAnnotations(final NodeList<AnnotationExpr> annotations, final Void arg) {
+        if (annotations.isEmpty()) {
+            return;
+        }
+        for (final AnnotationExpr a : annotations) {
+            a.accept(this, arg);
+            printer.println();
+        }
+    }
+
+    private void printAnnotations(final NodeList<AnnotationExpr> annotations, boolean prefixWithASpace, final Void arg) {
+        if (annotations.isEmpty()) {
+            return;
+        }
+        if (prefixWithASpace) {
+            printer.print(" ");
+        }
+        for (AnnotationExpr annotation : annotations) {
+            annotation.accept(this, arg);
+            printer.print(" ");
+        }
+    }
+
+    private void printTypeArgs(final NodeWithTypeArguments<?> nodeWithTypeArguments, final Void arg) {
+        NodeList<Type> typeArguments = nodeWithTypeArguments.getTypeArguments().orElse(null);
+        if (!isNullOrEmpty(typeArguments)) {
+            printer.print("<");
+            for (final Iterator<Type> i = typeArguments.iterator(); i.hasNext(); ) {
+                final Type t = i.next();
+                t.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+            printer.print(">");
+        }
+    }
+
+    private void printTypeParameters(final NodeList<TypeParameter> args, final Void arg) {
+        if (!isNullOrEmpty(args)) {
+            printer.print("<");
+            for (final Iterator<TypeParameter> i = args.iterator(); i.hasNext(); ) {
+                final TypeParameter t = i.next();
+                t.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+            printer.print(">");
+        }
+    }
+
+    private void printArguments(final NodeList<Expression> args, final Void arg) {
+        printer.print("(");
+        if (!isNullOrEmpty(args)) {
+            for (final Iterator<Expression> i = args.iterator(); i.hasNext(); ) {
+                final Expression e = i.next();
+                e.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.print(")");
+    }
+
+    private void printJavaComment(final Comment javacomment, final Void arg) {
+        if (javacomment != null) {
+            javacomment.accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final CompilationUnit n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getPackageDeclaration().isPresent()) {
+            n.getPackageDeclaration().get().accept(this, arg);
+        }
+        n.getImports().accept(this, arg);
+        if (!n.getImports().isEmpty()) {
+            printer.println();
+        }
+        for (final Iterator<TypeDeclaration<?>> i = n.getTypes().iterator(); i.hasNext(); ) {
+            i.next().accept(this, arg);
+            printer.println();
+            if (i.hasNext()) {
+                printer.println();
+            }
+        }
+        printOrphanCommentsEnding(n);
+    }
+
+    @Override
+    public void visit(final PackageDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), false, arg);
+        printer.print("package ");
+        n.getName().accept(this, arg);
+        printer.println(";");
+        printer.println();
+        printOrphanCommentsEnding(n);
+    }
+
+    @Override
+    public void visit(final NameExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getName().accept(this, arg);
+        printOrphanCommentsEnding(n);
+    }
+
+    @Override
+    public void visit(final Name n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getQualifier().isPresent()) {
+            n.getQualifier().get().accept(this, arg);
+            printer.print(".");
+        }
+        printer.print(n.getIdentifier());
+        printOrphanCommentsEnding(n);
+    }
+
+    @Override
+    public void visit(SimpleName n, Void arg) {
+        printer.print(n.getIdentifier());
+    }
+
+    @Override
+    public void visit(final ClassOrInterfaceDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        printModifiers(n.getModifiers());
+        if (n.isInterface()) {
+            printer.print("interface ");
+        } else {
+            printer.print("class ");
+        }
+        n.getName().accept(this, arg);
+        printTypeParameters(n.getTypeParameters(), arg);
+        if (!n.getExtendedTypes().isEmpty()) {
+            printer.print(" extends ");
+            for (final Iterator<ClassOrInterfaceType> i = n.getExtendedTypes().iterator(); i.hasNext(); ) {
+                final ClassOrInterfaceType c = i.next();
+                c.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        if (!n.getImplementedTypes().isEmpty()) {
+            printer.print(" implements ");
+            for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) {
+                final ClassOrInterfaceType c = i.next();
+                c.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.println(" {");
+        printer.indent();
+        if (!isNullOrEmpty(n.getMembers())) {
+            printMembers(n.getMembers(), arg);
+        }
+        printOrphanCommentsEnding(n);
+        printer.unindent();
+        printer.print("}");
+    }
+
+    @Override
+    public void visit(final JavadocComment n, final Void arg) {
+        printer.print("/**");
+        printer.print(n.getContent());
+        printer.println("*/");
+    }
+
+    @Override
+    public void visit(final ClassOrInterfaceType n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getScope().isPresent()) {
+            n.getScope().get().accept(this, arg);
+            printer.print(".");
+        }
+        for (AnnotationExpr ae : n.getAnnotations()) {
+            ae.accept(this, arg);
+            printer.print(" ");
+        }
+        n.getName().accept(this, arg);
+        if (n.isUsingDiamondOperator()) {
+            printer.print("<>");
+        } else {
+            printTypeArgs(n, arg);
+        }
+    }
+
+    @Override
+    public void visit(final TypeParameter n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        for (AnnotationExpr ann : n.getAnnotations()) {
+            ann.accept(this, arg);
+            printer.print(" ");
+        }
+        n.getName().accept(this, arg);
+        if (!isNullOrEmpty(n.getTypeBound())) {
+            printer.print(" extends ");
+            for (final Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext(); ) {
+                final ClassOrInterfaceType c = i.next();
+                c.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(" & ");
+                }
+            }
+        }
+    }
+
+    @Override
+    public void visit(final PrimitiveType n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), true, arg);
+        printer.print(n.getType().asString());
+    }
+
+    @Override
+    public void visit(final ArrayType n, final Void arg) {
+        final List<ArrayType> arrayTypeBuffer = new LinkedList<>();
+        Type type = n;
+        while (type instanceof ArrayType) {
+            final ArrayType arrayType = (ArrayType) type;
+            arrayTypeBuffer.add(arrayType);
+            type = arrayType.getComponentType();
+        }
+        type.accept(this, arg);
+        for (ArrayType arrayType : arrayTypeBuffer) {
+            printAnnotations(arrayType.getAnnotations(), true, arg);
+            printer.print("[]");
+        }
+    }
+
+    @Override
+    public void visit(final ArrayCreationLevel n, final Void arg) {
+        printAnnotations(n.getAnnotations(), true, arg);
+        printer.print("[");
+        if (n.getDimension().isPresent()) {
+            n.getDimension().get().accept(this, arg);
+        }
+        printer.print("]");
+    }
+
+    @Override
+    public void visit(final IntersectionType n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), false, arg);
+        boolean isFirst = true;
+        for (ReferenceType element : n.getElements()) {
+            element.accept(this, arg);
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                printer.print(" & ");
+            }
+        }
+    }
+
+    @Override
+    public void visit(final UnionType n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), true, arg);
+        boolean isFirst = true;
+        for (ReferenceType element : n.getElements()) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                printer.print(" | ");
+            }
+            element.accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final WildcardType n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), false, arg);
+        printer.print("?");
+        if (n.getExtendedTypes().isPresent()) {
+            printer.print(" extends ");
+            n.getExtendedTypes().get().accept(this, arg);
+        }
+        if (n.getSuperTypes().isPresent()) {
+            printer.print(" super ");
+            n.getSuperTypes().get().accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final UnknownType n, final Void arg) {
+    // Nothing to print
+    }
+
+    @Override
+    public void visit(final FieldDeclaration n, final Void arg) {
+        printOrphanCommentsBeforeThisChildNode(n);
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        printModifiers(n.getModifiers());
+        if (!n.getVariables().isEmpty()) {
+            n.getMaximumCommonType().accept(this, arg);
+        }
+        printer.print(" ");
+        for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) {
+            final VariableDeclarator var = i.next();
+            var.accept(this, arg);
+            if (i.hasNext()) {
+                printer.print(", ");
+            }
+        }
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final VariableDeclarator n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getName().accept(this, arg);
+        Type commonType = n.getAncestorOfType(NodeWithVariables.class).get().getMaximumCommonType();
+        Type type = n.getType();
+        ArrayType arrayType = null;
+        for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) {
+            if (arrayType == null) {
+                arrayType = (ArrayType) type;
+            } else {
+                arrayType = (ArrayType) arrayType.getComponentType();
+            }
+            printAnnotations(arrayType.getAnnotations(), true, arg);
+            printer.print("[]");
+        }
+        if (n.getInitializer().isPresent()) {
+            printer.print(" = ");
+            n.getInitializer().get().accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final ArrayInitializerExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("{");
+        if (!isNullOrEmpty(n.getValues())) {
+            printer.print(" ");
+            for (final Iterator<Expression> i = n.getValues().iterator(); i.hasNext(); ) {
+                final Expression expr = i.next();
+                expr.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+            printer.print(" ");
+        }
+        printer.print("}");
+    }
+
+    @Override
+    public void visit(final VoidType n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), false, arg);
+        printer.print("void");
+    }
+
+    @Override
+    public void visit(final ArrayAccessExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getName().accept(this, arg);
+        printer.print("[");
+        n.getIndex().accept(this, arg);
+        printer.print("]");
+    }
+
+    @Override
+    public void visit(final ArrayCreationExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("new ");
+        n.getElementType().accept(this, arg);
+        for (ArrayCreationLevel level : n.getLevels()) {
+            level.accept(this, arg);
+        }
+        if (n.getInitializer().isPresent()) {
+            printer.print(" ");
+            n.getInitializer().get().accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final AssignExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getTarget().accept(this, arg);
+        printer.print(" ");
+        printer.print(n.getOperator().asString());
+        printer.print(" ");
+        n.getValue().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final BinaryExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getLeft().accept(this, arg);
+        printer.print(" ");
+        printer.print(n.getOperator().asString());
+        printer.print(" ");
+        n.getRight().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final CastExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("(");
+        n.getType().accept(this, arg);
+        printer.print(") ");
+        n.getExpression().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final ClassExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getType().accept(this, arg);
+        printer.print(".class");
+    }
+
+    @Override
+    public void visit(final ConditionalExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getCondition().accept(this, arg);
+        printer.print(" ? ");
+        n.getThenExpr().accept(this, arg);
+        printer.print(" : ");
+        n.getElseExpr().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final EnclosedExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("(");
+        if (n.getInner().isPresent()) {
+            n.getInner().get().accept(this, arg);
+        }
+        printer.print(")");
+    }
+
+    @Override
+    public void visit(final FieldAccessExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getScope().isPresent())
+            n.getScope().get().accept(this, arg);
+        printer.print(".");
+        n.getName().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final InstanceOfExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getExpression().accept(this, arg);
+        printer.print(" instanceof ");
+        n.getType().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final CharLiteralExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("'");
+        printer.print(n.getValue());
+        printer.print("'");
+    }
+
+    @Override
+    public void visit(final DoubleLiteralExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print(n.getValue());
+    }
+
+    @Override
+    public void visit(final IntegerLiteralExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print(n.getValue());
+    }
+
+    @Override
+    public void visit(final LongLiteralExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print(n.getValue());
+    }
+
+    @Override
+    public void visit(final StringLiteralExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("\"");
+        printer.print(n.getValue());
+        printer.print("\"");
+    }
+
+    @Override
+    public void visit(final BooleanLiteralExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print(String.valueOf(n.getValue()));
+    }
+
+    @Override
+    public void visit(final NullLiteralExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("null");
+    }
+
+    @Override
+    public void visit(final ThisExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getClassExpr().isPresent()) {
+            n.getClassExpr().get().accept(this, arg);
+            printer.print(".");
+        }
+        printer.print("this");
+    }
+
+    @Override
+    public void visit(final SuperExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getClassExpr().isPresent()) {
+            n.getClassExpr().get().accept(this, arg);
+            printer.print(".");
+        }
+        printer.print("super");
+    }
+
+    @Override
+    public void visit(final MethodCallExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getScope().isPresent()) {
+            n.getScope().get().accept(this, arg);
+            printer.print(".");
+        }
+        printTypeArgs(n, arg);
+        n.getName().accept(this, arg);
+        printArguments(n.getArguments(), arg);
+    }
+
+    @Override
+    public void visit(final ObjectCreationExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getScope().isPresent()) {
+            n.getScope().get().accept(this, arg);
+            printer.print(".");
+        }
+        printer.print("new ");
+        printTypeArgs(n, arg);
+        if (!isNullOrEmpty(n.getTypeArguments().orElse(null))) {
+            printer.print(" ");
+        }
+        n.getType().accept(this, arg);
+        printArguments(n.getArguments(), arg);
+        if (n.getAnonymousClassBody().isPresent()) {
+            printer.println(" {");
+            printer.indent();
+            printMembers(n.getAnonymousClassBody().get(), arg);
+            printer.unindent();
+            printer.print("}");
+        }
+    }
+
+    @Override
+    public void visit(final UnaryExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getOperator().isPrefix()) {
+            printer.print(n.getOperator().asString());
+        }
+        n.getExpression().accept(this, arg);
+        if (n.getOperator().isPostfix()) {
+            printer.print(n.getOperator().asString());
+        }
+    }
+
+    @Override
+    public void visit(final ConstructorDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        printModifiers(n.getModifiers());
+        printTypeParameters(n.getTypeParameters(), arg);
+        if (n.isGeneric()) {
+            printer.print(" ");
+        }
+        n.getName().accept(this, arg);
+        printer.print("(");
+        if (!n.getParameters().isEmpty()) {
+            for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) {
+                final Parameter p = i.next();
+                p.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.print(")");
+        if (!isNullOrEmpty(n.getThrownExceptions())) {
+            printer.print(" throws ");
+            for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) {
+                final ReferenceType name = i.next();
+                name.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.print(" ");
+        n.getBody().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final MethodDeclaration n, final Void arg) {
+        printOrphanCommentsBeforeThisChildNode(n);
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        printModifiers(n.getModifiers());
+        if (n.isDefault()) {
+            printer.print("default ");
+        }
+        printTypeParameters(n.getTypeParameters(), arg);
+        if (!isNullOrEmpty(n.getTypeParameters())) {
+            printer.print(" ");
+        }
+        n.getType().accept(this, arg);
+        printer.print(" ");
+        n.getName().accept(this, arg);
+        printer.print("(");
+        if (!isNullOrEmpty(n.getParameters())) {
+            for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) {
+                final Parameter p = i.next();
+                p.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.print(")");
+        if (!isNullOrEmpty(n.getThrownExceptions())) {
+            printer.print(" throws ");
+            for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) {
+                final ReferenceType name = i.next();
+                name.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        if (!n.getBody().isPresent()) {
+            printer.print(";");
+        } else {
+            printer.print(" ");
+            n.getBody().get().accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final Parameter n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), false, arg);
+        printModifiers(n.getModifiers());
+        if (n.getType() != null) {
+            n.getType().accept(this, arg);
+        }
+        if (n.isVarArgs()) {
+            printer.print("...");
+        }
+        printer.print(" ");
+        n.getName().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final ExplicitConstructorInvocationStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.isThis()) {
+            printTypeArgs(n, arg);
+            printer.print("this");
+        } else {
+            if (n.getExpression().isPresent()) {
+                n.getExpression().get().accept(this, arg);
+                printer.print(".");
+            }
+            printTypeArgs(n, arg);
+            printer.print("super");
+        }
+        printArguments(n.getArguments(), arg);
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final VariableDeclarationExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printAnnotations(n.getAnnotations(), false, arg);
+        printModifiers(n.getModifiers());
+        if (!n.getVariables().isEmpty()) {
+            n.getMaximumCommonType().accept(this, arg);
+        }
+        printer.print(" ");
+        for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) {
+            final VariableDeclarator v = i.next();
+            v.accept(this, arg);
+            if (i.hasNext()) {
+                printer.print(", ");
+            }
+        }
+    }
+
+    @Override
+    public void visit(final LocalClassDeclarationStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getClassDeclaration().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final AssertStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("assert ");
+        n.getCheck().accept(this, arg);
+        if (n.getMessage().isPresent()) {
+            printer.print(" : ");
+            n.getMessage().get().accept(this, arg);
+        }
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final BlockStmt n, final Void arg) {
+        printOrphanCommentsBeforeThisChildNode(n);
+        printJavaComment(n.getComment(), arg);
+        printer.println("{");
+        if (n.getStatements() != null) {
+            printer.indent();
+            for (final Statement s : n.getStatements()) {
+                s.accept(this, arg);
+                printer.println();
+            }
+            printer.unindent();
+        }
+        printOrphanCommentsEnding(n);
+        printer.print("}");
+    }
+
+    @Override
+    public void visit(final LabeledStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getLabel().accept(this, arg);
+        printer.print(": ");
+        n.getStatement().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final EmptyStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final ExpressionStmt n, final Void arg) {
+        printOrphanCommentsBeforeThisChildNode(n);
+        printJavaComment(n.getComment(), arg);
+        n.getExpression().accept(this, arg);
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final SwitchStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("switch(");
+        n.getSelector().accept(this, arg);
+        printer.println(") {");
+        if (n.getEntries() != null) {
+            printer.indent();
+            for (final SwitchEntryStmt e : n.getEntries()) {
+                e.accept(this, arg);
+            }
+            printer.unindent();
+        }
+        printer.print("}");
+    }
+
+    @Override
+    public void visit(final SwitchEntryStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getLabel().isPresent()) {
+            printer.print("case ");
+            n.getLabel().get().accept(this, arg);
+            printer.print(":");
+        } else {
+            printer.print("default:");
+        }
+        printer.println();
+        printer.indent();
+        if (n.getStatements() != null) {
+            for (final Statement s : n.getStatements()) {
+                s.accept(this, arg);
+                printer.println();
+            }
+        }
+        printer.unindent();
+    }
+
+    @Override
+    public void visit(final BreakStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("break");
+        n.getLabel().ifPresent( l -> printer.print(" ").print(l.getIdentifier()));
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final ReturnStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("return");
+        if (n.getExpression().isPresent()) {
+            printer.print(" ");
+            n.getExpression().get().accept(this, arg);
+        }
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final EnumDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        printModifiers(n.getModifiers());
+        printer.print("enum ");
+        n.getName().accept(this, arg);
+        if (!n.getImplementedTypes().isEmpty()) {
+            printer.print(" implements ");
+            for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) {
+                final ClassOrInterfaceType c = i.next();
+                c.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.println(" {");
+        printer.indent();
+        if (n.getEntries() != null) {
+            printer.println();
+            for (final Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext(); ) {
+                final EnumConstantDeclaration e = i.next();
+                e.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        if (!n.getMembers().isEmpty()) {
+            printer.println(";");
+            printMembers(n.getMembers(), arg);
+        } else {
+            if (!n.getEntries().isEmpty()) {
+                printer.println();
+            }
+        }
+        printer.unindent();
+        printer.print("}");
+    }
+
+    @Override
+    public void visit(final EnumConstantDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        n.getName().accept(this, arg);
+        if (!n.getArguments().isEmpty()) {
+            printArguments(n.getArguments(), arg);
+        }
+        if (!n.getClassBody().isEmpty()) {
+            printer.println(" {");
+            printer.indent();
+            printMembers(n.getClassBody(), arg);
+            printer.unindent();
+            printer.println("}");
+        }
+    }
+
+    @Override
+    public void visit(final EmptyMemberDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final InitializerDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.isStatic()) {
+            printer.print("static ");
+        }
+        n.getBody().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final IfStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("if (");
+        n.getCondition().accept(this, arg);
+        final boolean thenBlock = n.getThenStmt() instanceof BlockStmt;
+        if (// block statement should start on the same line
+        thenBlock)
+            printer.print(") ");
+        else {
+            printer.println(")");
+            printer.indent();
+        }
+        n.getThenStmt().accept(this, arg);
+        if (!thenBlock)
+            printer.unindent();
+        if (n.getElseStmt().isPresent()) {
+            if (thenBlock)
+                printer.print(" ");
+            else
+                printer.println();
+            final boolean elseIf = n.getElseStmt().orElse(null) instanceof IfStmt;
+            final boolean elseBlock = n.getElseStmt().orElse(null) instanceof BlockStmt;
+            if (// put chained if and start of block statement on a same level
+            elseIf || elseBlock)
+                printer.print("else ");
+            else {
+                printer.println("else");
+                printer.indent();
+            }
+            if (n.getElseStmt().isPresent())
+                n.getElseStmt().get().accept(this, arg);
+            if (!(elseIf || elseBlock))
+                printer.unindent();
+        }
+    }
+
+    @Override
+    public void visit(final WhileStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("while (");
+        n.getCondition().accept(this, arg);
+        printer.print(") ");
+        n.getBody().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final ContinueStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("continue");
+        n.getLabel().ifPresent( l -> printer.print(" ").print(l.getIdentifier()));
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final DoStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("do ");
+        n.getBody().accept(this, arg);
+        printer.print(" while (");
+        n.getCondition().accept(this, arg);
+        printer.print(");");
+    }
+
+    @Override
+    public void visit(final ForeachStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("for (");
+        n.getVariable().accept(this, arg);
+        printer.print(" : ");
+        n.getIterable().accept(this, arg);
+        printer.print(") ");
+        n.getBody().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final ForStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("for (");
+        if (n.getInitialization() != null) {
+            for (final Iterator<Expression> i = n.getInitialization().iterator(); i.hasNext(); ) {
+                final Expression e = i.next();
+                e.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.print("; ");
+        if (n.getCompare().isPresent()) {
+            n.getCompare().get().accept(this, arg);
+        }
+        printer.print("; ");
+        if (n.getUpdate() != null) {
+            for (final Iterator<Expression> i = n.getUpdate().iterator(); i.hasNext(); ) {
+                final Expression e = i.next();
+                e.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.print(") ");
+        n.getBody().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final ThrowStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("throw ");
+        n.getExpression().accept(this, arg);
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final SynchronizedStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("synchronized (");
+        n.getExpression().accept(this, arg);
+        printer.print(") ");
+        n.getBody().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final TryStmt n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("try ");
+        if (!n.getResources().isEmpty()) {
+            printer.print("(");
+            Iterator<VariableDeclarationExpr> resources = n.getResources().iterator();
+            boolean first = true;
+            while (resources.hasNext()) {
+                visit(resources.next(), arg);
+                if (resources.hasNext()) {
+                    printer.print(";");
+                    printer.println();
+                    if (first) {
+                        printer.indent();
+                    }
+                }
+                first = false;
+            }
+            if (n.getResources().size() > 1) {
+                printer.unindent();
+            }
+            printer.print(") ");
+        }
+        if (n.getTryBlock().isPresent()) {
+            n.getTryBlock().get().accept(this, arg);
+        }
+        for (final CatchClause c : n.getCatchClauses()) {
+            c.accept(this, arg);
+        }
+        if (n.getFinallyBlock().isPresent()) {
+            printer.print(" finally ");
+            n.getFinallyBlock().get().accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final CatchClause n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print(" catch (");
+        n.getParameter().accept(this, arg);
+        printer.print(") ");
+        n.getBody().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final AnnotationDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        printModifiers(n.getModifiers());
+        printer.print("@interface ");
+        n.getName().accept(this, arg);
+        printer.println(" {");
+        printer.indent();
+        if (n.getMembers() != null) {
+            printMembers(n.getMembers(), arg);
+        }
+        printer.unindent();
+        printer.print("}");
+    }
+
+    @Override
+    public void visit(final AnnotationMemberDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
+        printModifiers(n.getModifiers());
+        n.getType().accept(this, arg);
+        printer.print(" ");
+        n.getName().accept(this, arg);
+        printer.print("()");
+        if (n.getDefaultValue().isPresent()) {
+            printer.print(" default ");
+            n.getDefaultValue().get().accept(this, arg);
+        }
+        printer.print(";");
+    }
+
+    @Override
+    public void visit(final MarkerAnnotationExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("@");
+        n.getName().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final SingleMemberAnnotationExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("@");
+        n.getName().accept(this, arg);
+        printer.print("(");
+        n.getMemberValue().accept(this, arg);
+        printer.print(")");
+    }
+
+    @Override
+    public void visit(final NormalAnnotationExpr n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("@");
+        n.getName().accept(this, arg);
+        printer.print("(");
+        if (n.getPairs() != null) {
+            for (final Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext(); ) {
+                final MemberValuePair m = i.next();
+                m.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+        }
+        printer.print(")");
+    }
+
+    @Override
+    public void visit(final MemberValuePair n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        n.getName().accept(this, arg);
+        printer.print(" = ");
+        n.getValue().accept(this, arg);
+    }
+
+    @Override
+    public void visit(final LineComment n, final Void arg) {
+        if (!configuration.isPrintComments()) {
+            return;
+        }
+        printer.print("//");
+        String tmp = n.getContent();
+        tmp = tmp.replace('\r', ' ');
+        tmp = tmp.replace('\n', ' ');
+        printer.println(tmp);
+    }
+
+    @Override
+    public void visit(final BlockComment n, final Void arg) {
+        if (!configuration.isPrintComments()) {
+            return;
+        }
+        printer.print("/*").print(n.getContent()).println("*/");
+    }
+
+    @Override
+    public void visit(LambdaExpr n, Void arg) {
+        printJavaComment(n.getComment(), arg);
+        final NodeList<Parameter> parameters = n.getParameters();
+        final boolean printPar = n.isEnclosingParameters();
+        if (printPar) {
+            printer.print("(");
+        }
+        for (Iterator<Parameter> i = parameters.iterator(); i.hasNext(); ) {
+            Parameter p = i.next();
+            p.accept(this, arg);
+            if (i.hasNext()) {
+                printer.print(", ");
+            }
+        }
+        if (printPar) {
+            printer.print(")");
+        }
+        printer.print(" -> ");
+        final Statement body = n.getBody();
+        if (body instanceof ExpressionStmt) {
+            // Print the expression directly
+            ((ExpressionStmt) body).getExpression().accept(this, arg);
+        } else {
+            body.accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(MethodReferenceExpr n, Void arg) {
+        printJavaComment(n.getComment(), arg);
+        Expression scope = n.getScope();
+        String identifier = n.getIdentifier();
+        if (scope != null) {
+            n.getScope().accept(this, arg);
+        }
+        printer.print("::");
+        printTypeArgs(n, arg);
+        if (identifier != null) {
+            printer.print(identifier);
+        }
+    }
+
+    @Override
+    public void visit(TypeExpr n, Void arg) {
+        printJavaComment(n.getComment(), arg);
+        if (n.getType() != null) {
+            n.getType().accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(NodeList n, Void arg) {
+        for (Object node : n) {
+            ((Node) node).accept(this, arg);
+        }
+    }
+
+    @Override
+    public void visit(final ImportDeclaration n, final Void arg) {
+        printJavaComment(n.getComment(), arg);
+        printer.print("import ");
+        if (n.isStatic()) {
+            printer.print("static ");
+        }
+        n.getName().accept(this, arg);
+        if (n.isAsterisk()) {
+            printer.print(".*");
+        }
+        printer.println(";");
+        printOrphanCommentsEnding(n);
+    }
+
+    private void printOrphanCommentsBeforeThisChildNode(final Node node) {
+        if (node instanceof Comment)
+            return;
+        Node parent = node.getParentNode().orElse(null);
+        if (parent == null)
+            return;
+        List<Node> everything = new LinkedList<>();
+        everything.addAll(parent.getChildNodes());
+        sortByBeginPosition(everything);
+        int positionOfTheChild = -1;
+        for (int i = 0; i < everything.size(); i++) {
+            if (everything.get(i) == node)
+                positionOfTheChild = i;
+        }
+        if (positionOfTheChild == -1) {
+            throw new AssertionError("I am not a child of my parent.");
+        }
+        int positionOfPreviousChild = -1;
+        for (int i = positionOfTheChild - 1; i >= 0 && positionOfPreviousChild == -1; i--) {
+            if (!(everything.get(i) instanceof Comment))
+                positionOfPreviousChild = i;
+        }
+        for (int i = positionOfPreviousChild + 1; i < positionOfTheChild; i++) {
+            Node nodeToPrint = everything.get(i);
+            if (!(nodeToPrint instanceof Comment))
+                throw new RuntimeException("Expected comment, instead " + nodeToPrint.getClass() + ". Position of previous child: " + positionOfPreviousChild + ", position of child " + positionOfTheChild);
+            nodeToPrint.accept(this, null);
+        }
+    }
+
+    private void printOrphanCommentsEnding(final Node node) {
+        List<Node> everything = new LinkedList<>();
+        everything.addAll(node.getChildNodes());
+        sortByBeginPosition(everything);
+        if (everything.isEmpty()) {
+            return;
+        }
+        int commentsAtEnd = 0;
+        boolean findingComments = true;
+        while (findingComments && commentsAtEnd < everything.size()) {
+            Node last = everything.get(everything.size() - 1 - commentsAtEnd);
+            findingComments = (last instanceof Comment);
+            if (findingComments) {
+                commentsAtEnd++;
+            }
+        }
+        for (int i = 0; i < commentsAtEnd; i++) {
+            everything.get(everything.size() - commentsAtEnd + i).accept(this, null);
+        }
+    }
+}
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlParsingJavadocWithQuoteAndNewline.yaml b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlParsingJavadocWithQuoteAndNewline.yaml
new file mode 100644
index 0000000..b26e836
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlParsingJavadocWithQuoteAndNewline.yaml
@@ -0,0 +1,13 @@
+---
+root(Type=CompilationUnit): 
+    types: 
+        - type(Type=ClassOrInterfaceDeclaration): 
+            isInterface: "false"
+            name(Type=SimpleName): 
+                identifier: "Dog"
+            comment(Type=JavadocComment): 
+                content: "\n * \" this comment contains a quote and newlines\n "
+            modifiers: 
+                - modifier(Type=Modifier): 
+                    keyword: "PUBLIC"
+...
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithColonFollowedByLineSeparatorInValue.yaml b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithColonFollowedByLineSeparatorInValue.yaml
new file mode 100644
index 0000000..fb538b3
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithColonFollowedByLineSeparatorInValue.yaml
@@ -0,0 +1,4 @@
+---
+root(Type=StringLiteralExpr): 
+    value: "a\\\\:\\\\nb"
+...
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithColonFollowedBySpaceInValue.yaml b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithColonFollowedBySpaceInValue.yaml
new file mode 100644
index 0000000..99f3617
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithColonFollowedBySpaceInValue.yaml
@@ -0,0 +1,4 @@
+---
+root(Type=StringLiteralExpr): 
+    value: "a\\\\: b"
+...
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithType.yaml b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithType.yaml
new file mode 100644
index 0000000..8e1d121
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithType.yaml
@@ -0,0 +1,10 @@
+---
+root(Type=MethodCallExpr): 
+    name(Type=SimpleName): 
+        identifier: "x"
+    arguments: 
+        - argument(Type=IntegerLiteralExpr): 
+            value: "1"
+        - argument(Type=IntegerLiteralExpr): 
+            value: "1"
+...
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithoutType.yaml b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithoutType.yaml
new file mode 100644
index 0000000..d96bcf2
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/printer/yamlWithoutType.yaml
@@ -0,0 +1,8 @@
+---
+root: 
+    operator: "PLUS"
+    left: 
+        value: "1"
+    right: 
+        value: "1"
+...
\ No newline at end of file
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/range/A.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/range/A.java
new file mode 100644
index 0000000..2104414
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/range/A.java
@@ -0,0 +1,7 @@
+package com.github.javaparser.range;
+
+public class A {
+    public void foo() {
+        int a = 42;
+    }
+}
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/range/B.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/range/B.java
new file mode 100644
index 0000000..f8f6fbe
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/range/B.java
@@ -0,0 +1,7 @@
+package com.github.javaparser.range;
+
+public class B {
+    public void foo() {
+        int b = 42;
+    }
+}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.txt b/javaparser-core-testing/src/test/resources/com/github/javaparser/source_zip/test.txt
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.txt
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/source_zip/test.txt
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.zip b/javaparser-core-testing/src/test/resources/com/github/javaparser/source_zip/test.zip
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/source_zip/test.zip
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/source_zip/test.zip
Binary files differ
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/storage/A.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/storage/A.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/storage/A.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/storage/A.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/storage/B.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/storage/B.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/storage/B.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/storage/B.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/storage/PrimaryType.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/storage/PrimaryType.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/storage/PrimaryType.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/storage/PrimaryType.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/storage/PrimaryType2.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/storage/PrimaryType2.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/storage/PrimaryType2.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/storage/PrimaryType2.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/storage/Z.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/storage/Z.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/storage/Z.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/storage/Z.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/utils/.abc/bla.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/.abc/bla.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/utils/.abc/bla.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/utils/.abc/bla.java
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/Bla.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/Bla.java
new file mode 100644
index 0000000..eeeb6f1
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/Bla.java
@@ -0,0 +1,2 @@
+class X {
+}
diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/module-info.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/module-info.java
new file mode 100644
index 0000000..a4a0ddb
--- /dev/null
+++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/module-info.java
@@ -0,0 +1,2 @@
+module M.N {
+}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/utils/source/root/Y.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/source.root/Y.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/utils/source/root/Y.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/utils/source.root/Y.java
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/wiki_samples/TestFile.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/wiki_samples/TestFile.java
similarity index 100%
rename from javaparser-testing/src/test/resources/com/github/javaparser/wiki_samples/TestFile.java
rename to javaparser-core-testing/src/test/resources/com/github/javaparser/wiki_samples/TestFile.java
diff --git a/javaparser-testing/src/test/test_sourcecode/com/github/javaparser/printer/JavaConcepts.java b/javaparser-core-testing/src/test/test_sourcecode/com/github/javaparser/printer/JavaConcepts.java
similarity index 100%
rename from javaparser-testing/src/test/test_sourcecode/com/github/javaparser/printer/JavaConcepts.java
rename to javaparser-core-testing/src/test/test_sourcecode/com/github/javaparser/printer/JavaConcepts.java
diff --git a/javaparser-testing/src/test/test_sourcecode/com/github/javaparser/printer/PrettyPrintVisitor.java b/javaparser-core-testing/src/test/test_sourcecode/com/github/javaparser/printer/PrettyPrintVisitor.java
similarity index 100%
rename from javaparser-testing/src/test/test_sourcecode/com/github/javaparser/printer/PrettyPrintVisitor.java
rename to javaparser-core-testing/src/test/test_sourcecode/com/github/javaparser/printer/PrettyPrintVisitor.java
diff --git a/javaparser-core/bnd.bnd b/javaparser-core/bnd.bnd
index 9f43eea..d6d8966 100644
--- a/javaparser-core/bnd.bnd
+++ b/javaparser-core/bnd.bnd
@@ -9,6 +9,8 @@
     com.github.javaparser.metamodel, \
     com.github.javaparser.printer, \
     com.github.javaparser.printer.concretesyntaxmodel, \
+    com.github.javaparser.printer.lexicalpreservation, \
+    com.github.javaparser.printer.lexicalpreservation.changes, \
     com.github.javaparser.resolution, \
     com.github.javaparser.resolution.declarations, \
     com.github.javaparser.resolution.types, \
diff --git a/javaparser-core/generated-sources/java-templates/com/github/javaparser/JavaParserBuild.java b/javaparser-core/generated-sources/java-templates/com/github/javaparser/JavaParserBuild.java
index 1fb494e..4fb5d41 100644
--- a/javaparser-core/generated-sources/java-templates/com/github/javaparser/JavaParserBuild.java
+++ b/javaparser-core/generated-sources/java-templates/com/github/javaparser/JavaParserBuild.java
@@ -4,16 +4,16 @@
  * Some information that was available when this library was built by Maven.
  */
 public class JavaParserBuild {
-    public static final String PROJECT_VERSION = "3.5.16-SNAPSHOT";
+    public static final String PROJECT_VERSION = "3.14.6-SNAPSHOT";
     public static final String PROJECT_NAME = "javaparser-core";
-    public static final String PROJECT_BUILD_FINAL_NAME = "javaparser-core-3.5.16-SNAPSHOT";
-    public static final String MAVEN_VERSION = "3.3.9";
-    public static final String MAVEN_BUILD_VERSION = "Apache Maven 3.3.9";
-    public static final String MAVEN_BUILD_TIMESTAMP = "2018-04-25T22:45:26Z";
-    public static final String JAVA_VENDOR ="Oracle Corporation";
-    public static final String JAVA_VENDOR_URL ="http://java.oracle.com/";
-    public static final String JAVA_VERSION ="9";
+    public static final String PROJECT_BUILD_FINAL_NAME = "javaparser-core-3.14.6-SNAPSHOT";
+    public static final String MAVEN_VERSION = "3.5.3";
+    public static final String MAVEN_BUILD_VERSION = "Apache Maven 3.5.3";
+    public static final String MAVEN_BUILD_TIMESTAMP = "2019-07-31T17:41:28Z";
+    public static final String JAVA_VENDOR ="Google Inc.";
+    public static final String JAVA_VENDOR_URL ="https://goto.google.com/java-platform";
+    public static final String JAVA_VERSION ="1.8.0_181-google-v7";
     public static final String OS_ARCH ="amd64";
     public static final String OS_NAME ="Linux";
-    public static final String OS_VERSION ="4.9.0-6-amd64";
+    public static final String OS_VERSION ="4.19.37-5rodete2-amd64";
 }
\ No newline at end of file
diff --git a/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParser.java b/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParser.java
index 88d8068..38dafa4 100644
--- a/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParser.java
+++ b/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParser.java
@@ -31,7 +31,6 @@
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
 import com.github.javaparser.utils.*;
-import javax.annotation.Generated;
 import static com.github.javaparser.JavaToken.INVALID;
 import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
 import static com.github.javaparser.utils.Utils.*;
@@ -41,6 +40,7 @@
 import static com.github.javaparser.Position.*;
 import static com.github.javaparser.ast.type.ArrayType.*;
 import static com.github.javaparser.GeneratedJavaParserTokenManagerBase.*;
+import static com.github.javaparser.ast.stmt.SwitchEntry.Type.*;
 
 @Generated("JavaCC")
 final class GeneratedJavaParser extends GeneratedJavaParserBase implements GeneratedJavaParserConstants {
@@ -72,8 +72,8 @@
         NodeList<ImportDeclaration> imports = emptyList();
         ImportDeclaration in = null;
         NodeList<TypeDeclaration<?>> types = emptyList();
-   ModifierHolder modifier;
-        TypeDeclaration tn = null;
+    ModifierHolder modifier;
+        TypeDeclaration<?> tn = null;
         ModuleDeclaration module = null;
     try {
       label_1:
@@ -260,7 +260,7 @@
  */
   final public 
 ModifierHolder Modifiers() throws ParseException {JavaToken begin = INVALID;
-    EnumSet<Modifier> modifiers = EnumSet.noneOf(Modifier.class);
+    NodeList<Modifier> modifiers = new NodeList<Modifier>();
         NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>();
     AnnotationExpr ann;
     label_3:
@@ -273,67 +273,67 @@
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case PUBLIC:{
         jj_consume_token(PUBLIC);
-addModifier(modifiers, Modifier.PUBLIC); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PUBLIC)); begin = orIfInvalid(begin, token());
         break;
         }
       case STATIC:{
         jj_consume_token(STATIC);
-addModifier(modifiers, Modifier.STATIC); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.STATIC)); begin = orIfInvalid(begin, token());
         break;
         }
       case PROTECTED:{
         jj_consume_token(PROTECTED);
-addModifier(modifiers, Modifier.PROTECTED); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PROTECTED)); begin = orIfInvalid(begin, token());
         break;
         }
       case PRIVATE:{
         jj_consume_token(PRIVATE);
-addModifier(modifiers, Modifier.PRIVATE); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PRIVATE)); begin = orIfInvalid(begin, token());
         break;
         }
       case FINAL:{
         jj_consume_token(FINAL);
-addModifier(modifiers, Modifier.FINAL); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.FINAL)); begin = orIfInvalid(begin, token());
         break;
         }
       case ABSTRACT:{
         jj_consume_token(ABSTRACT);
-addModifier(modifiers, Modifier.ABSTRACT); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.ABSTRACT)); begin = orIfInvalid(begin, token());
         break;
         }
       case SYNCHRONIZED:{
         jj_consume_token(SYNCHRONIZED);
-addModifier(modifiers, Modifier.SYNCHRONIZED); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.SYNCHRONIZED)); begin = orIfInvalid(begin, token());
         break;
         }
       case NATIVE:{
         jj_consume_token(NATIVE);
-addModifier(modifiers, Modifier.NATIVE); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.NATIVE)); begin = orIfInvalid(begin, token());
         break;
         }
       case TRANSIENT:{
         jj_consume_token(TRANSIENT);
-addModifier(modifiers, Modifier.TRANSIENT); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.TRANSIENT)); begin = orIfInvalid(begin, token());
         break;
         }
       case VOLATILE:{
         jj_consume_token(VOLATILE);
-addModifier(modifiers, Modifier.VOLATILE); begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.VOLATILE)); begin = orIfInvalid(begin, token());
         break;
         }
       case STRICTFP:{
         jj_consume_token(STRICTFP);
-addModifier(modifiers, Modifier.STRICTFP);  begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.STRICTFP));  begin = orIfInvalid(begin, token());
         break;
         }
       case TRANSITIVE:{
         jj_consume_token(TRANSITIVE);
-addModifier(modifiers, Modifier.TRANSITIVE);  begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.TRANSITIVE));  begin = orIfInvalid(begin, token());
         break;
         }
       case _DEFAULT:{
         jj_consume_token(_DEFAULT);
-addModifier(modifiers, Modifier.DEFAULT);  begin = orIfInvalid(begin, token());
+add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.DEFAULT));  begin = orIfInvalid(begin, token());
         break;
         }
       case AT:{
@@ -1060,6 +1060,7 @@
     case SHORT:
     case STRICTFP:
     case SUPER:
+    case SWITCH:
     case THIS:
     case TRUE:
     case VOID:
@@ -1118,6 +1119,7 @@
     case SHORT:
     case STRICTFP:
     case SUPER:
+    case SWITCH:
     case THIS:
     case TRUE:
     case VOID:
@@ -1413,7 +1415,7 @@
   final public NodeList<Parameter> InferredLambdaParameters() throws ParseException {NodeList<Parameter> ret = null;
     Pair<SimpleName, List<ArrayBracketPair>> id;
     id = VariableDeclaratorId();
-ret = add(ret, new Parameter(range(id.a, id.a), EnumSet.noneOf(Modifier.class), emptyList(), new UnknownType(), false, emptyList(), id.a));
+ret = add(ret, new Parameter(range(id.a, id.a), new NodeList<Modifier>(), emptyList(), new UnknownType(), false, emptyList(), id.a));
     label_19:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
@@ -1427,7 +1429,7 @@
       }
       jj_consume_token(COMMA);
       id = VariableDeclaratorId();
-ret = add(ret, new Parameter(range(id.a, id.a), EnumSet.noneOf(Modifier.class), emptyList(), new UnknownType(), false, emptyList(), id.a));
+ret = add(ret, new Parameter(range(id.a, id.a), new NodeList<Modifier>(), emptyList(), new UnknownType(), false, emptyList(), id.a));
     }
 return ret;
 }
@@ -1466,16 +1468,14 @@
 }
 
   final public Name ReceiverParameterId() throws ParseException {Name ret = null;
-        NodeList<AnnotationExpr> annotations;
     if (jj_2_12(2147483647)) {
       ret = Name();
       jj_consume_token(DOT);
     } else {
       ;
     }
-    annotations = Annotations();
     jj_consume_token(THIS);
-return new Name(tokenRange(), ret, token.image, annotations);
+return new Name(tokenRange(), ret, token.image);
 }
 
   final public ConstructorDeclaration ConstructorDeclaration(ModifierHolder modifier) throws ParseException {RangedList<TypeParameter> typeParameters = new RangedList<TypeParameter>(emptyList());
@@ -2070,21 +2070,18 @@
 }
 
   final public Name Name() throws ParseException {Name ret;
-        NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>();
-    annotations = Annotations();
     Identifier();
-ret = new Name(tokenRange(), null, token.image, annotations);
+ret = new Name(tokenRange(), null, token.image);
     label_27:
     while (true) {
-      if (jj_2_23(2147483647)) {
+      if (jj_2_23(2)) {
         ;
       } else {
         break label_27;
       }
       jj_consume_token(DOT);
-      annotations = Annotations();
       Identifier();
-ret = new Name(range(ret, token()), ret, token.image, annotations);
+ret = new Name(range(ret, token()), ret, token.image);
     }
 return ret;
 }
@@ -2726,6 +2723,7 @@
     case SHORT:
     case STRICTFP:
     case SUPER:
+    case SWITCH:
     case THIS:
     case TRUE:
     case VOID:
@@ -2848,6 +2846,10 @@
           ret = PostfixExpression();
           break;
           }
+        case SWITCH:{
+          ret = SwitchExpression();
+          break;
+          }
         default:
           jj_la1[90] = jj_gen;
           jj_consume_token(-1);
@@ -3128,6 +3130,7 @@
           case SHORT:
           case STRICTFP:
           case SUPER:
+          case SWITCH:
           case THIS:
           case TRUE:
           case VOID:
@@ -3273,7 +3276,7 @@
       case DOT:{
         jj_consume_token(DOT);
         jj_consume_token(SUPER);
-ret = new SuperExpr(range(scope, token()), scope);
+ret = new SuperExpr(range(scope, token()), scopeToName(scope));
         break;
         }
       default:
@@ -3296,7 +3299,7 @@
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case THIS:{
         jj_consume_token(THIS);
-ret = new ThisExpr(range(scope, token()), scope);
+ret = new ThisExpr(range(scope, token()), scopeToName(scope));
         break;
         }
       case NEW:{
@@ -3439,6 +3442,7 @@
     case SHORT:
     case STRICTFP:
     case SUPER:
+    case SWITCH:
     case THIS:
     case TRUE:
     case VOID:
@@ -3508,6 +3512,15 @@
         NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>();
     jj_consume_token(NEW);
 if(scope==null) {begin=token();} else {begin = orIfInvalid(begin, scope);}
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case LT:{
+      typeArgs = TypeArguments();
+      break;
+      }
+    default:
+      jj_la1[115] = jj_gen;
+      ;
+    }
     annotations = Annotations();
     switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
     case BOOLEAN:
@@ -3534,19 +3547,8 @@
     case EXPORTS:
     case PROVIDES:
     case TRANSITIVE:
-    case IDENTIFIER:
-    case AT:
-    case LT:{
-      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
-      case LT:{
-        typeArgs = TypeArguments();
-        break;
-        }
-      default:
-        jj_la1[115] = jj_gen;
-        ;
-      }
-      type = AnnotatedClassOrInterfaceType();
+    case IDENTIFIER:{
+      type = ClassOrInterfaceType(annotations);
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case LBRACKET:
       case AT:{
@@ -3605,6 +3607,7 @@
       case SHORT:
       case STRICTFP:
       case SUPER:
+      case SWITCH:
       case THIS:
       case TRUE:
       case VOID:
@@ -3959,6 +3962,7 @@
     case SHORT:
     case STRICTFP:
     case SUPER:
+    case SWITCH:
     case THIS:
     case TRUE:
     case VOID:
@@ -4118,8 +4122,8 @@
 }
 
   final public SwitchStmt SwitchStatement() throws ParseException {Expression selector;
-        SwitchEntryStmt entry;
-        NodeList<SwitchEntryStmt> entries = emptyList();
+        SwitchEntry entry;
+        NodeList<SwitchEntry> entries = emptyList();
         JavaToken begin;
     jj_consume_token(SWITCH);
 begin=token();
@@ -4146,14 +4150,63 @@
 return new SwitchStmt(range(begin, token()), selector, entries);
 }
 
-  final public SwitchEntryStmt SwitchEntry() throws ParseException {Expression label = null;
-        NodeList<Statement> stmts;
+  final public SwitchExpr SwitchExpression() throws ParseException {Expression selector;
+        SwitchEntry entry;
+        NodeList<SwitchEntry> entries = emptyList();
         JavaToken begin;
+    jj_consume_token(SWITCH);
+begin=token();
+    jj_consume_token(LPAREN);
+    selector = Expression();
+    jj_consume_token(RPAREN);
+    jj_consume_token(LBRACE);
+    label_45:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case CASE:
+      case _DEFAULT:{
+        ;
+        break;
+        }
+      default:
+        jj_la1[129] = jj_gen;
+        break label_45;
+      }
+      entry = SwitchEntry();
+entries = add(entries, entry);
+    }
+    jj_consume_token(RBRACE);
+return new SwitchExpr(range(begin, token()), selector, entries);
+}
+
+  final public SwitchEntry SwitchEntry() throws ParseException {Expression label = null;
+        NodeList<Expression> labels = emptyList();
+        NodeList<Statement> stmts = emptyList();
+        JavaToken begin;
+        SwitchEntry ret;
+        Expression expression = null;
+        Statement stmt = null;
     switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
     case CASE:{
       jj_consume_token(CASE);
 begin=token();
-      label = Expression();
+      label = ConditionalExpression();
+labels = add(labels, label);
+      label_46:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+        case COMMA:{
+          ;
+          break;
+          }
+        default:
+          jj_la1[130] = jj_gen;
+          break label_46;
+        }
+        jj_consume_token(COMMA);
+        label = ConditionalExpression();
+labels = add(labels, label);
+      }
       break;
       }
     case _DEFAULT:{
@@ -4162,13 +4215,96 @@
       break;
       }
     default:
-      jj_la1[129] = jj_gen;
+      jj_la1[131] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
-    jj_consume_token(COLON);
-    stmts = Statements();
-return new SwitchEntryStmt(range(begin, token()),label, stmts);
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case COLON:{
+      jj_consume_token(COLON);
+      stmts = Statements();
+ret = new SwitchEntry(range(begin, token()), labels, STATEMENT_GROUP, stmts);
+      break;
+      }
+    case ARROW:{
+      jj_consume_token(ARROW);
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case BOOLEAN:
+      case BYTE:
+      case CHAR:
+      case DOUBLE:
+      case ENUM:
+      case FALSE:
+      case FLOAT:
+      case INT:
+      case LONG:
+      case NEW:
+      case NULL:
+      case SHORT:
+      case STRICTFP:
+      case SUPER:
+      case SWITCH:
+      case THIS:
+      case TRUE:
+      case VOID:
+      case REQUIRES:
+      case TO:
+      case WITH:
+      case OPEN:
+      case OPENS:
+      case USES:
+      case MODULE:
+      case EXPORTS:
+      case PROVIDES:
+      case TRANSITIVE:
+      case LONG_LITERAL:
+      case INTEGER_LITERAL:
+      case FLOATING_POINT_LITERAL:
+      case CHARACTER_LITERAL:
+      case STRING_LITERAL:
+      case IDENTIFIER:
+      case LPAREN:
+      case AT:
+      case BANG:
+      case TILDE:
+      case INCR:
+      case DECR:
+      case PLUS:
+      case MINUS:{
+        expression = Expression();
+        jj_consume_token(SEMICOLON);
+TokenRange r=range(begin, token());
+                                stmts.add(new ExpressionStmt(r, expression));
+                                ret = new SwitchEntry(r, labels, EXPRESSION, stmts);
+        break;
+        }
+      case LBRACE:{
+        stmt = Block();
+TokenRange r=range(begin, token());
+                                stmts.add(stmt);
+                                ret = new SwitchEntry(r, labels, BLOCK, stmts);
+        break;
+        }
+      case THROW:{
+        stmt = ThrowStatement();
+TokenRange r=range(begin, token());
+                                stmts.add(stmt);
+                                ret = new SwitchEntry(r, labels, THROWS_STATEMENT, stmts);
+        break;
+        }
+      default:
+        jj_la1[132] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      break;
+      }
+    default:
+      jj_la1[133] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+return ret;
 }
 
   final public IfStmt IfStatement() throws ParseException {Expression condition;
@@ -4190,7 +4326,7 @@
       break;
       }
     default:
-      jj_la1[130] = jj_gen;
+      jj_la1[134] = jj_gen;
       ;
     }
 return new IfStmt(range(begin, token()), condition, thenStmt, elseStmt);
@@ -4259,6 +4395,7 @@
       case STATIC:
       case STRICTFP:
       case SUPER:
+      case SWITCH:
       case SYNCHRONIZED:
       case THIS:
       case TRANSIENT:
@@ -4313,6 +4450,7 @@
         case STATIC:
         case STRICTFP:
         case SUPER:
+        case SWITCH:
         case SYNCHRONIZED:
         case THIS:
         case TRANSIENT:
@@ -4347,7 +4485,7 @@
           break;
           }
         default:
-          jj_la1[131] = jj_gen;
+          jj_la1[135] = jj_gen;
           ;
         }
         jj_consume_token(SEMICOLON);
@@ -4366,6 +4504,7 @@
         case SHORT:
         case STRICTFP:
         case SUPER:
+        case SWITCH:
         case THIS:
         case TRUE:
         case VOID:
@@ -4397,7 +4536,7 @@
           break;
           }
         default:
-          jj_la1[132] = jj_gen;
+          jj_la1[136] = jj_gen;
           ;
         }
         jj_consume_token(SEMICOLON);
@@ -4416,6 +4555,7 @@
         case SHORT:
         case STRICTFP:
         case SUPER:
+        case SWITCH:
         case THIS:
         case TRUE:
         case VOID:
@@ -4447,13 +4587,13 @@
           break;
           }
         default:
-          jj_la1[133] = jj_gen;
+          jj_la1[137] = jj_gen;
           ;
         }
         break;
         }
       default:
-        jj_la1[134] = jj_gen;
+        jj_la1[138] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -4461,7 +4601,7 @@
     jj_consume_token(RPAREN);
     body = Statement();
 if (varExpr != null) {
-                return new ForeachStmt(range(begin, token()),varExpr, expr, body);
+                return new ForEachStmt(range(begin, token()),varExpr, expr, body);
         }
         return new ForStmt(range(begin, token()),init, expr, update, body);
 }
@@ -4487,6 +4627,7 @@
       case SHORT:
       case STRICTFP:
       case SUPER:
+      case SWITCH:
       case THIS:
       case TRUE:
       case VOID:
@@ -4518,7 +4659,7 @@
         break;
         }
       default:
-        jj_la1[135] = jj_gen;
+        jj_la1[139] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -4530,7 +4671,7 @@
         Expression expr;
     expr = Expression();
 ret.add(expr);
-    label_45:
+    label_47:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case COMMA:{
@@ -4538,8 +4679,8 @@
         break;
         }
       default:
-        jj_la1[136] = jj_gen;
-        break label_45;
+        jj_la1[140] = jj_gen;
+        break label_47;
       }
       jj_consume_token(COMMA);
       expr = Expression();
@@ -4553,13 +4694,29 @@
 return ret;
 }
 
-  final public BreakStmt BreakStatement() throws ParseException {SimpleName label = null;
+  final public BreakStmt BreakStatement() throws ParseException {Expression value = null;
         JavaToken begin;
     jj_consume_token(BREAK);
 begin=token();
     switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case BOOLEAN:
+    case BYTE:
+    case CHAR:
+    case DOUBLE:
     case ENUM:
+    case FALSE:
+    case FLOAT:
+    case INT:
+    case LONG:
+    case NEW:
+    case NULL:
+    case SHORT:
     case STRICTFP:
+    case SUPER:
+    case SWITCH:
+    case THIS:
+    case TRUE:
+    case VOID:
     case REQUIRES:
     case TO:
     case WITH:
@@ -4570,16 +4727,29 @@
     case EXPORTS:
     case PROVIDES:
     case TRANSITIVE:
-    case IDENTIFIER:{
-      label = SimpleName();
+    case LONG_LITERAL:
+    case INTEGER_LITERAL:
+    case FLOATING_POINT_LITERAL:
+    case CHARACTER_LITERAL:
+    case STRING_LITERAL:
+    case IDENTIFIER:
+    case LPAREN:
+    case AT:
+    case BANG:
+    case TILDE:
+    case INCR:
+    case DECR:
+    case PLUS:
+    case MINUS:{
+      value = Expression();
       break;
       }
     default:
-      jj_la1[137] = jj_gen;
+      jj_la1[141] = jj_gen;
       ;
     }
     jj_consume_token(SEMICOLON);
-return new BreakStmt(range(begin, token()), label);
+return new BreakStmt(range(begin, token()), value);
 }
 
   final public ContinueStmt ContinueStatement() throws ParseException {SimpleName label = null;
@@ -4604,7 +4774,7 @@
       break;
       }
     default:
-      jj_la1[138] = jj_gen;
+      jj_la1[142] = jj_gen;
       ;
     }
     jj_consume_token(SEMICOLON);
@@ -4630,6 +4800,7 @@
     case SHORT:
     case STRICTFP:
     case SUPER:
+    case SWITCH:
     case THIS:
     case TRUE:
     case VOID:
@@ -4661,7 +4832,7 @@
       break;
       }
     default:
-      jj_la1[139] = jj_gen;
+      jj_la1[143] = jj_gen;
       ;
     }
     jj_consume_token(SEMICOLON);
@@ -4711,11 +4882,11 @@
       break;
       }
     default:
-      jj_la1[140] = jj_gen;
+      jj_la1[144] = jj_gen;
       ;
     }
     tryBlock = Block();
-    label_46:
+    label_48:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case CATCH:{
@@ -4723,17 +4894,17 @@
         break;
         }
       default:
-        jj_la1[141] = jj_gen;
-        break label_46;
+        jj_la1[145] = jj_gen;
+        break label_48;
       }
       jj_consume_token(CATCH);
 catchBegin=token();
       jj_consume_token(LPAREN);
-typesBegin=token();
       exceptModifier = Modifiers();
+typesBegin = exceptModifier.begin;
       exceptionType = ReferenceType(emptyList());
-exceptionTypes.add(exceptionType);
-      label_47:
+exceptionTypes.add(exceptionType); typesBegin = orIfInvalid(typesBegin, token());
+      label_49:
       while (true) {
         switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
         case BIT_OR:{
@@ -4741,8 +4912,8 @@
           break;
           }
         default:
-          jj_la1[142] = jj_gen;
-          break label_47;
+          jj_la1[146] = jj_gen;
+          break label_49;
         }
         jj_consume_token(BIT_OR);
         exceptionType = AnnotatedReferenceType();
@@ -4757,7 +4928,7 @@
                             } else {
                                 type = (Type)exceptionTypes.get(0);
                             }
-                                Parameter catchType = new Parameter(range(type, paramEnd), exceptModifier.modifiers, exceptModifier.annotations, type, false, emptyList(), exceptId.a);
+                                Parameter catchType = new Parameter(range(typesBegin, paramEnd), exceptModifier.modifiers, exceptModifier.annotations, type, false, emptyList(), exceptId.a);
                             catchs = add(catchs, new CatchClause(range(catchBegin, token()), catchType, catchBlock));
                             exceptionTypes = emptyList();
     }
@@ -4768,7 +4939,7 @@
       break;
       }
     default:
-      jj_la1[143] = jj_gen;
+      jj_la1[147] = jj_gen;
       ;
     }
 return new TryStmt(range(begin, token()), resources, tryBlock, catchs, finallyBlock);
@@ -4790,12 +4961,12 @@
         Expression expr;
     expr = Resource();
 expressions.add(expr);
-    label_48:
+    label_50:
     while (true) {
       if (jj_2_48(2)) {
         ;
       } else {
-        break label_48;
+        break label_50;
       }
       jj_consume_token(SEMICOLON);
       expr = Resource();
@@ -4849,7 +5020,7 @@
         break;
         }
       default:
-        jj_la1[144] = jj_gen;
+        jj_la1[148] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -4890,12 +5061,12 @@
   final public 
 NodeList<AnnotationExpr> Annotations() throws ParseException {NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>();
         AnnotationExpr annotation;
-    label_49:
+    label_51:
     while (true) {
       if (jj_2_50(2147483647)) {
         ;
       } else {
-        break label_49;
+        break label_51;
       }
       annotation = Annotation();
 annotations = add(annotations, annotation);
@@ -4931,7 +5102,7 @@
         break;
         }
       default:
-        jj_la1[145] = jj_gen;
+        jj_la1[149] = jj_gen;
         ;
       }
       jj_consume_token(RPAREN);
@@ -4951,7 +5122,7 @@
         MemberValuePair pair;
     pair = MemberValuePair();
 ret.add(pair);
-    label_50:
+    label_52:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case COMMA:{
@@ -4959,8 +5130,8 @@
         break;
         }
       default:
-        jj_la1[146] = jj_gen;
-        break label_50;
+        jj_la1[150] = jj_gen;
+        break label_52;
       }
       jj_consume_token(COMMA);
       pair = MemberValuePair();
@@ -5002,6 +5173,7 @@
       case SHORT:
       case STRICTFP:
       case SUPER:
+      case SWITCH:
       case THIS:
       case TRUE:
       case VOID:
@@ -5033,7 +5205,7 @@
         break;
         }
       default:
-        jj_la1[147] = jj_gen;
+        jj_la1[151] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -5061,6 +5233,7 @@
     case SHORT:
     case STRICTFP:
     case SUPER:
+    case SWITCH:
     case THIS:
     case TRUE:
     case VOID:
@@ -5091,12 +5264,12 @@
     case MINUS:{
       member = MemberValue();
 ret.add(member);
-      label_51:
+      label_53:
       while (true) {
         if (jj_2_54(2)) {
           ;
         } else {
-          break label_51;
+          break label_53;
         }
         jj_consume_token(COMMA);
         member = MemberValue();
@@ -5105,7 +5278,7 @@
       break;
       }
     default:
-      jj_la1[148] = jj_gen;
+      jj_la1[152] = jj_gen;
       ;
     }
     switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
@@ -5114,7 +5287,7 @@
       break;
       }
     default:
-      jj_la1[149] = jj_gen;
+      jj_la1[153] = jj_gen;
       ;
     }
     jj_consume_token(RBRACE);
@@ -5137,7 +5310,7 @@
   final public NodeList<BodyDeclaration<?>> AnnotationTypeBody() throws ParseException {NodeList<BodyDeclaration<?>> ret = emptyList();
         BodyDeclaration member;
     jj_consume_token(LBRACE);
-    label_52:
+    label_54:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case ABSTRACT:
@@ -5180,8 +5353,8 @@
         break;
         }
       default:
-        jj_la1[150] = jj_gen;
-        break label_52;
+        jj_la1[154] = jj_gen;
+        break label_54;
       }
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case ABSTRACT:
@@ -5228,7 +5401,7 @@
         break;
         }
       default:
-        jj_la1[151] = jj_gen;
+        jj_la1[155] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -5250,7 +5423,7 @@
         break;
         }
       default:
-        jj_la1[152] = jj_gen;
+        jj_la1[156] = jj_gen;
         if (jj_2_56(2147483647)) {
           ret = EnumDeclaration(modifier);
         } else {
@@ -5284,7 +5457,7 @@
             break;
             }
           default:
-            jj_la1[153] = jj_gen;
+            jj_la1[157] = jj_gen;
             jj_consume_token(-1);
             throw new ParseException();
           }
@@ -5307,7 +5480,7 @@
       break;
       }
     default:
-      jj_la1[154] = jj_gen;
+      jj_la1[158] = jj_gen;
       ;
     }
     jj_consume_token(SEMICOLON);
@@ -5324,15 +5497,12 @@
 /* Module syntax follows */
   final public 
 
-ModuleStmt ModuleStmt() throws ParseException {ModifierHolder modifiers;
+ModuleDirective ModuleDirective() throws ParseException {ModifierHolder modifiers;
     Name name;
     Name tmpName;
     NodeList<Name> names=emptyList();
-    Type type;
-    Type tmpType;
-    NodeList<Type> types=emptyList();
     JavaToken begin;
-    ModuleStmt stmt=new ModuleRequiresStmt();
+    ModuleDirective directive;
     JavaToken transitiveExceptionalToken;
     if (jj_2_57(2147483647)) {
       jj_consume_token(REQUIRES);
@@ -5340,7 +5510,7 @@
       jj_consume_token(TRANSITIVE);
 transitiveExceptionalToken=token(); setTokenKind(IDENTIFIER);
       jj_consume_token(SEMICOLON);
-stmt=new ModuleRequiresStmt(range(begin, token()), EnumSet.noneOf(Modifier.class), new Name(range(transitiveExceptionalToken, transitiveExceptionalToken), null, transitiveExceptionalToken.getText(), new NodeList<AnnotationExpr>()));
+directive=new ModuleRequiresDirective(range(begin, token()), new NodeList<Modifier>(), new Name(range(transitiveExceptionalToken, transitiveExceptionalToken), null, transitiveExceptionalToken.getText()));
     } else {
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case REQUIRES:{
@@ -5349,7 +5519,7 @@
         modifiers = Modifiers();
         name = Name();
         jj_consume_token(SEMICOLON);
-stmt=new ModuleRequiresStmt(range(begin, token()), modifiers.modifiers, name);
+directive=new ModuleRequiresDirective(range(begin, token()), modifiers.modifiers, name);
         break;
         }
       case EXPORTS:{
@@ -5361,7 +5531,7 @@
           jj_consume_token(TO);
           tmpName = Name();
 names.add(tmpName);
-          label_53:
+          label_55:
           while (true) {
             switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
             case COMMA:{
@@ -5369,8 +5539,8 @@
               break;
               }
             default:
-              jj_la1[155] = jj_gen;
-              break label_53;
+              jj_la1[159] = jj_gen;
+              break label_55;
             }
             jj_consume_token(COMMA);
             tmpName = Name();
@@ -5379,11 +5549,11 @@
           break;
           }
         default:
-          jj_la1[156] = jj_gen;
+          jj_la1[160] = jj_gen;
           ;
         }
         jj_consume_token(SEMICOLON);
-stmt=new ModuleExportsStmt(range(begin, token()), name, names);
+directive=new ModuleExportsDirective(range(begin, token()), name, names);
         break;
         }
       case OPENS:{
@@ -5395,7 +5565,7 @@
           jj_consume_token(TO);
           tmpName = Name();
 names.add(tmpName);
-          label_54:
+          label_56:
           while (true) {
             switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
             case COMMA:{
@@ -5403,8 +5573,8 @@
               break;
               }
             default:
-              jj_la1[157] = jj_gen;
-              break label_54;
+              jj_la1[161] = jj_gen;
+              break label_56;
             }
             jj_consume_token(COMMA);
             tmpName = Name();
@@ -5413,29 +5583,29 @@
           break;
           }
         default:
-          jj_la1[158] = jj_gen;
+          jj_la1[162] = jj_gen;
           ;
         }
         jj_consume_token(SEMICOLON);
-stmt=new ModuleOpensStmt(range(begin, token()), name, names);
+directive=new ModuleOpensDirective(range(begin, token()), name, names);
         break;
         }
       case USES:{
         jj_consume_token(USES);
 begin=token();
-        type = Type(emptyList());
+        name = Name();
         jj_consume_token(SEMICOLON);
-stmt=new ModuleUsesStmt(range(begin, token()), type);
+directive=new ModuleUsesDirective(range(begin, token()), name);
         break;
         }
       case PROVIDES:{
         jj_consume_token(PROVIDES);
 begin=token();
-        type = Type(emptyList());
+        name = Name();
         jj_consume_token(WITH);
-        tmpType = Type(emptyList());
-types.add(tmpType);
-        label_55:
+        tmpName = Name();
+names.add(tmpName);
+        label_57:
         while (true) {
           switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
           case COMMA:{
@@ -5443,29 +5613,29 @@
             break;
             }
           default:
-            jj_la1[159] = jj_gen;
-            break label_55;
+            jj_la1[163] = jj_gen;
+            break label_57;
           }
           jj_consume_token(COMMA);
-          tmpType = Type(emptyList());
-types.add(tmpType);
+          tmpName = Name();
+names.add(tmpName);
         }
         jj_consume_token(SEMICOLON);
-stmt=new ModuleProvidesStmt(range(begin, token()), type, types);
+directive=new ModuleProvidesDirective(range(begin, token()), name, names);
         break;
         }
       default:
-        jj_la1[160] = jj_gen;
+        jj_la1[164] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
     }
-return stmt;
+return directive;
 }
 
-  final public ModuleDeclaration ModuleDeclaration(ModifierHolder modifier) throws ParseException {NodeList<ModuleStmt> statements = new NodeList<ModuleStmt>();
+  final public ModuleDeclaration ModuleDeclaration(ModifierHolder modifier) throws ParseException {NodeList<ModuleDirective> directives = new NodeList<ModuleDirective>();
     boolean open=false;
-    ModuleStmt st;
+    ModuleDirective directive;
     Name name;
     JavaToken begin = modifier.begin;
     switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
@@ -5475,14 +5645,14 @@
       break;
       }
     default:
-      jj_la1[161] = jj_gen;
+      jj_la1[165] = jj_gen;
       ;
     }
     jj_consume_token(MODULE);
 begin = orIfInvalid(begin, token());
     name = Name();
     jj_consume_token(LBRACE);
-    label_56:
+    label_58:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
       case REQUIRES:
@@ -5494,14 +5664,14 @@
         break;
         }
       default:
-        jj_la1[162] = jj_gen;
-        break label_56;
+        jj_la1[166] = jj_gen;
+        break label_58;
       }
-      st = ModuleStmt();
-statements = add(statements, st);
+      directive = ModuleDirective();
+directives = add(directives, directive);
     }
     jj_consume_token(RBRACE);
-return new ModuleDeclaration(range(begin, token()), modifier.annotations, name, open, statements);
+return new ModuleDeclaration(range(begin, token()), modifier.annotations, name, open, directives);
 }
 
 /* Rules for matching partial inputs.
@@ -5562,7 +5732,7 @@
         break;
         }
       default:
-        jj_la1[163] = jj_gen;
+        jj_la1[167] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -5650,6 +5820,54 @@
 return ret;
 }
 
+  final public TypeDeclaration<?> TypeDeclarationParseStart() throws ParseException {TypeDeclaration<?> ret;
+        ModifierHolder modifier;
+    modifier = Modifiers();
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case CLASS:
+    case INTERFACE:{
+      ret = ClassOrInterfaceDeclaration(modifier);
+      break;
+      }
+    case ENUM:{
+      ret = EnumDeclaration(modifier);
+      break;
+      }
+    case AT:{
+      ret = AnnotationTypeDeclaration(modifier);
+      break;
+      }
+    default:
+      jj_la1[168] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    jj_consume_token(0);
+return ret;
+}
+
+  final public ModuleDeclaration ModuleDeclarationParseStart() throws ParseException {ModuleDeclaration ret;
+        ModifierHolder modifiers;
+    modifiers = Modifiers();
+    ret = ModuleDeclaration(modifiers);
+    jj_consume_token(0);
+return ret;
+}
+
+  final public ModuleDirective ModuleDirectiveParseStart() throws ParseException {ModuleDirective ret;
+    ret = ModuleDirective();
+    jj_consume_token(0);
+return ret;
+}
+
+  final public TypeParameter TypeParameterParseStart() throws ParseException {TypeParameter ret;
+        NodeList<AnnotationExpr> annotations;
+    annotations = Annotations();
+    ret = TypeParameter(annotations);
+    jj_consume_token(0);
+return ret;
+}
+
   private boolean jj_2_1(int xla)
  {
     jj_la = xla; jj_lastpos = jj_scanpos = token;
@@ -6114,336 +6332,359 @@
     finally { jj_save(57, xla); }
   }
 
-  private boolean jj_3R_304()
- {
-    if (jj_scan_token(EXTENDS)) return true;
-    if (jj_3R_306()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_408()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_296()
- {
-    if (jj_3R_324()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_364()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_227()
+  private boolean jj_3R_228()
  {
     if (jj_scan_token(INTERFACE)) return true;
     return false;
   }
 
-  private boolean jj_3R_262()
+  private boolean jj_3R_299()
  {
-    if (jj_3R_305()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_286()
- {
-    if (jj_scan_token(DO)) return true;
-    if (jj_3R_195()) return true;
-    if (jj_scan_token(WHILE)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_90()) return true;
-    if (jj_scan_token(RPAREN)) return true;
-    if (jj_scan_token(SEMICOLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_261()
- {
-    if (jj_3R_304()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_260()
- {
-    if (jj_3R_117()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_248()
- {
-    if (jj_3R_296()) return true;
+    if (jj_3R_327()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_348()) { jj_scanpos = xsp; break; }
+      if (jj_3R_373()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_194()
+  private boolean jj_3R_264()
+ {
+    if (jj_3R_309()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_263()
+ {
+    if (jj_3R_308()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_262()
+ {
+    if (jj_3R_119()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_195()
  {
     Token xsp;
     xsp = jj_scanpos;
     if (jj_scan_token(19)) {
     jj_scanpos = xsp;
-    if (jj_3R_227()) return true;
+    if (jj_3R_228()) return true;
     }
-    if (jj_3R_88()) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_260()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_261()) jj_scanpos = xsp;
+    if (jj_3R_90()) return true;
     xsp = jj_scanpos;
     if (jj_3R_262()) jj_scanpos = xsp;
-    if (jj_3R_105()) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_263()) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_264()) jj_scanpos = xsp;
+    if (jj_3R_107()) return true;
     return false;
   }
 
-  private boolean jj_3R_169()
+  private boolean jj_3R_249()
  {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_112()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_285()
- {
-    if (jj_scan_token(WHILE)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_90()) return true;
-    if (jj_scan_token(RPAREN)) return true;
-    if (jj_3R_195()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_328()
- {
-    if (jj_3R_74()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_200()
- {
-    if (jj_3R_248()) return true;
+    if (jj_3R_299()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_325()) { jj_scanpos = xsp; break; }
+      if (jj_3R_353()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_300()
+  private boolean jj_3R_380()
+ {
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(SEMICOLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_170()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_114()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_379()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_150()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_370()
+ {
+    if (jj_scan_token(_DEFAULT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_372()
+ {
+    if (jj_scan_token(ARROW)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_380()) {
+    jj_scanpos = xsp;
+    if (jj_3R_381()) {
+    jj_scanpos = xsp;
+    if (jj_3R_382()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_369()
+ {
+    if (jj_scan_token(CASE)) return true;
+    if (jj_3R_150()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_379()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_371()
+ {
+    if (jj_scan_token(COLON)) return true;
+    if (jj_3R_180()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_332()
+ {
+    if (jj_3R_76()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_201()
+ {
+    if (jj_3R_249()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_329()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_352()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_369()) {
+    jj_scanpos = xsp;
+    if (jj_3R_370()) return true;
+    }
+    xsp = jj_scanpos;
+    if (jj_3R_371()) {
+    jj_scanpos = xsp;
+    if (jj_3R_372()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_304()
  {
     if (jj_scan_token(HOOK)) return true;
-    if (jj_3R_90()) return true;
+    if (jj_3R_92()) return true;
     if (jj_scan_token(COLON)) return true;
-    if (jj_3R_149()) return true;
+    if (jj_3R_150()) return true;
     return false;
   }
 
-  private boolean jj_3R_149()
+  private boolean jj_3R_150()
  {
-    if (jj_3R_200()) return true;
+    if (jj_3R_201()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_300()) jj_scanpos = xsp;
+    if (jj_3R_304()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_284()
+  private boolean jj_3R_73()
  {
-    if (jj_scan_token(IF)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_90()) return true;
-    if (jj_scan_token(RPAREN)) return true;
-    if (jj_3R_195()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_411()) jj_scanpos = xsp;
+    if (jj_3R_117()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_72()
+ {
+    if (jj_scan_token(_DEFAULT)) return true;
     return false;
   }
 
   private boolean jj_3R_71()
  {
-    if (jj_3R_115()) return true;
+    if (jj_scan_token(TRANSITIVE)) return true;
     return false;
   }
 
   private boolean jj_3R_70()
  {
-    if (jj_scan_token(_DEFAULT)) return true;
+    if (jj_scan_token(STRICTFP)) return true;
     return false;
   }
 
-  private boolean jj_3R_69()
- {
-    if (jj_scan_token(TRANSITIVE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_148()
+  private boolean jj_3R_149()
  {
     if (jj_scan_token(ORASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_147()
- {
-    if (jj_scan_token(XORASSIGN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_68()
- {
-    if (jj_scan_token(STRICTFP)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_146()
- {
-    if (jj_scan_token(ANDASSIGN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_145()
- {
-    if (jj_scan_token(RUNSIGNEDSHIFTASSIGN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_431()
- {
-    if (jj_scan_token(_DEFAULT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_67()
+  private boolean jj_3R_69()
  {
     if (jj_scan_token(VOLATILE)) return true;
     return false;
   }
 
-  private boolean jj_3R_144()
+  private boolean jj_3R_148()
  {
-    if (jj_scan_token(RSIGNEDSHIFTASSIGN)) return true;
+    if (jj_scan_token(XORASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_143()
+  private boolean jj_3R_147()
  {
-    if (jj_scan_token(LSHIFTASSIGN)) return true;
+    if (jj_scan_token(ANDASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_430()
- {
-    if (jj_scan_token(CASE)) return true;
-    if (jj_3R_90()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_66()
+  private boolean jj_3R_68()
  {
     if (jj_scan_token(TRANSIENT)) return true;
     return false;
   }
 
-  private boolean jj_3R_142()
+  private boolean jj_3R_146()
  {
-    if (jj_scan_token(MINUSASSIGN)) return true;
+    if (jj_scan_token(RUNSIGNEDSHIFTASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_141()
+  private boolean jj_3R_145()
  {
-    if (jj_scan_token(PLUSASSIGN)) return true;
+    if (jj_scan_token(RSIGNEDSHIFTASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_65()
+  private boolean jj_3R_67()
  {
     if (jj_scan_token(NATIVE)) return true;
     return false;
   }
 
-  private boolean jj_3R_140()
+  private boolean jj_3R_144()
  {
-    if (jj_scan_token(REMASSIGN)) return true;
+    if (jj_scan_token(LSHIFTASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_139()
+  private boolean jj_3R_143()
  {
-    if (jj_scan_token(SLASHASSIGN)) return true;
+    if (jj_scan_token(MINUSASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_64()
+  private boolean jj_3R_328()
+ {
+    if (jj_3R_352()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_66()
  {
     if (jj_scan_token(SYNCHRONIZED)) return true;
     return false;
   }
 
-  private boolean jj_3R_138()
+  private boolean jj_3R_142()
  {
-    if (jj_scan_token(STARASSIGN)) return true;
+    if (jj_scan_token(PLUSASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_327()
+  private boolean jj_3R_141()
  {
-    if (jj_3R_87()) return true;
+    if (jj_scan_token(REMASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_137()
- {
-    if (jj_scan_token(ASSIGN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_63()
+  private boolean jj_3R_65()
  {
     if (jj_scan_token(ABSTRACT)) return true;
     return false;
   }
 
-  private boolean jj_3R_62()
+  private boolean jj_3R_140()
+ {
+    if (jj_scan_token(SLASHASSIGN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_139()
+ {
+    if (jj_scan_token(STARASSIGN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_331()
+ {
+    if (jj_3R_89()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_64()
  {
     if (jj_scan_token(FINAL)) return true;
     return false;
   }
 
-  private boolean jj_3R_424()
+  private boolean jj_3R_138()
  {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_430()) {
-    jj_scanpos = xsp;
-    if (jj_3R_431()) return true;
-    }
-    if (jj_scan_token(COLON)) return true;
-    if (jj_3R_179()) return true;
+    if (jj_scan_token(ASSIGN)) return true;
     return false;
   }
 
-  private boolean jj_3R_61()
+  private boolean jj_3R_303()
+ {
+    if (jj_scan_token(SWITCH)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_scan_token(LBRACE)) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_328()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(RBRACE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_63()
  {
     if (jj_scan_token(PRIVATE)) return true;
     return false;
   }
 
-  private boolean jj_3R_89()
+  private boolean jj_3R_62()
+ {
+    if (jj_scan_token(PROTECTED)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_91()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_137()) {
-    jj_scanpos = xsp;
     if (jj_3R_138()) {
     jj_scanpos = xsp;
     if (jj_3R_139()) {
@@ -6464,7 +6705,9 @@
     jj_scanpos = xsp;
     if (jj_3R_147()) {
     jj_scanpos = xsp;
-    if (jj_3R_148()) return true;
+    if (jj_3R_148()) {
+    jj_scanpos = xsp;
+    if (jj_3R_149()) return true;
     }
     }
     }
@@ -6479,14 +6722,20 @@
     return false;
   }
 
-  private boolean jj_3R_302()
+  private boolean jj_3R_61()
+ {
+    if (jj_scan_token(STATIC)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_306()
  {
     if (jj_scan_token(DOUBLECOLON)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_327()) jj_scanpos = xsp;
+    if (jj_3R_331()) jj_scanpos = xsp;
     xsp = jj_scanpos;
-    if (jj_3R_328()) {
+    if (jj_3R_332()) {
     jj_scanpos = xsp;
     if (jj_scan_token(42)) return true;
     }
@@ -6495,25 +6744,13 @@
 
   private boolean jj_3R_60()
  {
-    if (jj_scan_token(PROTECTED)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_59()
- {
-    if (jj_scan_token(STATIC)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_58()
- {
     if (jj_scan_token(PUBLIC)) return true;
     return false;
   }
 
-  private boolean jj_3R_410()
+  private boolean jj_3R_420()
  {
-    if (jj_3R_424()) return true;
+    if (jj_3R_352()) return true;
     return false;
   }
 
@@ -6521,10 +6758,6 @@
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_58()) {
-    jj_scanpos = xsp;
-    if (jj_3R_59()) {
-    jj_scanpos = xsp;
     if (jj_3R_60()) {
     jj_scanpos = xsp;
     if (jj_3R_61()) {
@@ -6547,7 +6780,11 @@
     jj_scanpos = xsp;
     if (jj_3R_70()) {
     jj_scanpos = xsp;
-    if (jj_3R_71()) return true;
+    if (jj_3R_71()) {
+    jj_scanpos = xsp;
+    if (jj_3R_72()) {
+    jj_scanpos = xsp;
+    if (jj_3R_73()) return true;
     }
     }
     }
@@ -6564,7 +6801,7 @@
     return false;
   }
 
-  private boolean jj_3R_108()
+  private boolean jj_3R_110()
  {
     Token xsp;
     while (true) {
@@ -6574,150 +6811,161 @@
     return false;
   }
 
-  private boolean jj_3R_283()
+  private boolean jj_3R_286()
  {
     if (jj_scan_token(SWITCH)) return true;
     if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_90()) return true;
+    if (jj_3R_92()) return true;
     if (jj_scan_token(RPAREN)) return true;
     if (jj_scan_token(LBRACE)) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_410()) { jj_scanpos = xsp; break; }
+      if (jj_3R_420()) { jj_scanpos = xsp; break; }
     }
     if (jj_scan_token(RBRACE)) return true;
     return false;
   }
 
-  private boolean jj_3R_301()
+  private boolean jj_3R_366()
+ {
+    if (jj_3R_91()) return true;
+    if (jj_3R_92()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_305()
  {
     if (jj_scan_token(ARROW)) return true;
-    if (jj_3R_326()) return true;
+    if (jj_3R_330()) return true;
     return false;
   }
 
-  private boolean jj_3R_361()
- {
-    if (jj_3R_89()) return true;
-    if (jj_3R_90()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_360()
+  private boolean jj_3R_365()
  {
     if (jj_scan_token(DECR)) return true;
     return false;
   }
 
-  private boolean jj_3_24()
- {
-    if (jj_3R_89()) return true;
-    if (jj_3R_90()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_359()
+  private boolean jj_3R_364()
  {
     if (jj_scan_token(INCR)) return true;
     return false;
   }
 
-  private boolean jj_3R_343()
+  private boolean jj_3R_347()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_359()) {
+    if (jj_3R_364()) {
     jj_scanpos = xsp;
-    if (jj_3R_360()) {
+    if (jj_3R_365()) {
     jj_scanpos = xsp;
-    if (jj_3R_361()) return true;
+    if (jj_3R_366()) return true;
     }
     }
     return false;
   }
 
-  private boolean jj_3R_255()
+  private boolean jj_3_24()
+ {
+    if (jj_3R_91()) return true;
+    if (jj_3R_92()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_257()
  {
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3_24()) {
     jj_scanpos = xsp;
-    if (jj_3R_301()) {
+    if (jj_3R_305()) {
     jj_scanpos = xsp;
-    if (jj_3R_302()) return true;
+    if (jj_3R_306()) return true;
     }
     }
     return false;
   }
 
-  private boolean jj_3R_318()
+  private boolean jj_3R_321()
  {
-    if (jj_3R_211()) return true;
+    if (jj_3R_212()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_343()) jj_scanpos = xsp;
+    if (jj_3R_347()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_90()
+  private boolean jj_3R_320()
  {
-    if (jj_3R_149()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_255()) jj_scanpos = xsp;
+    if (jj_3R_259()) return true;
     return false;
   }
 
-  private boolean jj_3R_317()
+  private boolean jj_3R_92()
  {
-    if (jj_3R_257()) return true;
+    if (jj_3R_150()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_257()) jj_scanpos = xsp;
     return false;
   }
 
   private boolean jj_3_44()
  {
-    if (jj_3R_110()) return true;
+    if (jj_3R_112()) return true;
     return false;
   }
 
-  private boolean jj_3R_282()
+  private boolean jj_3R_285()
  {
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3_44()) {
     jj_scanpos = xsp;
-    if (jj_3R_317()) {
+    if (jj_3R_320()) {
     jj_scanpos = xsp;
-    if (jj_3R_318()) return true;
+    if (jj_3R_321()) return true;
     }
     }
     if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
-  private boolean jj_3R_57()
+  private boolean jj_3R_59()
  {
-    if (jj_3R_86()) return true;
+    if (jj_3R_88()) return true;
     if (jj_scan_token(PACKAGE)) return true;
-    if (jj_3R_80()) return true;
+    if (jj_3R_82()) return true;
     if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
-  private boolean jj_3R_350()
+  private boolean jj_3R_355()
  {
-    if (jj_3R_121()) return true;
+    if (jj_3R_123()) return true;
     return false;
   }
 
-  private boolean jj_3R_349()
+  private boolean jj_3R_354()
  {
-    if (jj_3R_90()) return true;
+    if (jj_3R_92()) return true;
     return false;
   }
 
-  private boolean jj_3R_74()
+  private boolean jj_3R_330()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_354()) {
+    jj_scanpos = xsp;
+    if (jj_3R_355()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_76()
  {
     Token xsp;
     xsp = jj_scanpos;
@@ -6761,91 +7009,70 @@
     return false;
   }
 
-  private boolean jj_3R_326()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_349()) {
-    jj_scanpos = xsp;
-    if (jj_3R_350()) return true;
-    }
-    return false;
-  }
-
   private boolean jj_3_2()
  {
-    if (jj_3R_57()) return true;
+    if (jj_3R_59()) return true;
     return false;
   }
 
-  private boolean jj_3_23()
- {
-    if (jj_scan_token(DOT)) return true;
-    if (jj_3R_86()) return true;
-    if (jj_3R_74()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_281()
+  private boolean jj_3R_284()
  {
     if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
-  private boolean jj_3R_88()
- {
-    if (jj_3R_74()) return true;
-    return false;
-  }
-
   private boolean jj_3_1()
  {
     if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
-  private boolean jj_3R_125()
+  private boolean jj_3R_90()
  {
-    if (jj_scan_token(DOT)) return true;
-    if (jj_3R_86()) return true;
-    if (jj_3R_74()) return true;
+    if (jj_3R_76()) return true;
     return false;
   }
 
-  private boolean jj_3R_109()
+  private boolean jj_3R_111()
  {
-    if (jj_3R_108()) return true;
-    if (jj_3R_75()) return true;
-    if (jj_3R_112()) return true;
+    if (jj_3R_110()) return true;
+    if (jj_3R_77()) return true;
+    if (jj_3R_114()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_169()) { jj_scanpos = xsp; break; }
+      if (jj_3R_170()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_80()
+  private boolean jj_3_23()
  {
-    if (jj_3R_86()) return true;
-    if (jj_3R_74()) return true;
+    if (jj_scan_token(DOT)) return true;
+    if (jj_3R_76()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_82()
+ {
+    if (jj_3R_76()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_125()) { jj_scanpos = xsp; break; }
+      if (jj_3_23()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
   private boolean jj_3_43()
  {
-    if (jj_3R_109()) return true;
+    if (jj_3R_111()) return true;
     return false;
   }
 
   private boolean jj_3_42()
  {
-    if (jj_3R_108()) return true;
+    if (jj_3R_110()) return true;
     Token xsp;
     xsp = jj_scanpos;
     if (jj_scan_token(19)) {
@@ -6855,158 +7082,156 @@
     return false;
   }
 
-  private boolean jj_3R_132()
+  private boolean jj_3R_133()
  {
-    if (jj_3R_195()) return true;
+    if (jj_3R_196()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_168()
+ {
+    if (jj_3R_77()) return true;
     return false;
   }
 
   private boolean jj_3R_167()
  {
-    if (jj_3R_75()) return true;
+    if (jj_scan_token(VOID)) return true;
     return false;
   }
 
-  private boolean jj_3R_166()
+  private boolean jj_3R_132()
  {
-    if (jj_scan_token(VOID)) return true;
+    if (jj_3R_111()) return true;
+    if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
   private boolean jj_3R_131()
  {
-    if (jj_3R_109()) return true;
-    if (jj_scan_token(SEMICOLON)) return true;
+    if (jj_3R_110()) return true;
+    if (jj_3R_195()) return true;
     return false;
   }
 
-  private boolean jj_3R_130()
- {
-    if (jj_3R_108()) return true;
-    if (jj_3R_194()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_102()
+  private boolean jj_3R_104()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_166()) {
+    if (jj_3R_167()) {
     jj_scanpos = xsp;
-    if (jj_3R_167()) return true;
+    if (jj_3R_168()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_336()
+  private boolean jj_3R_340()
  {
     if (jj_scan_token(COLON)) return true;
-    if (jj_3R_90()) return true;
+    if (jj_3R_92()) return true;
     return false;
   }
 
-  private boolean jj_3R_84()
+  private boolean jj_3R_86()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_130()) {
-    jj_scanpos = xsp;
     if (jj_3R_131()) {
     jj_scanpos = xsp;
-    if (jj_3R_132()) return true;
+    if (jj_3R_132()) {
+    jj_scanpos = xsp;
+    if (jj_3R_133()) return true;
     }
     }
     return false;
   }
 
-  private boolean jj_3R_160()
+  private boolean jj_3R_161()
  {
     if (jj_scan_token(DOUBLE)) return true;
     return false;
   }
 
-  private boolean jj_3R_159()
+  private boolean jj_3R_160()
  {
     if (jj_scan_token(FLOAT)) return true;
     return false;
   }
 
-  private boolean jj_3R_158()
+  private boolean jj_3R_159()
  {
     if (jj_scan_token(LONG)) return true;
     return false;
   }
 
-  private boolean jj_3R_157()
+  private boolean jj_3R_158()
  {
     if (jj_scan_token(INT)) return true;
     return false;
   }
 
-  private boolean jj_3R_156()
+  private boolean jj_3R_157()
  {
     if (jj_scan_token(SHORT)) return true;
     return false;
   }
 
-  private boolean jj_3R_155()
+  private boolean jj_3R_156()
  {
     if (jj_scan_token(BYTE)) return true;
     return false;
   }
 
-  private boolean jj_3R_154()
+  private boolean jj_3R_155()
  {
     if (jj_scan_token(CHAR)) return true;
     return false;
   }
 
-  private boolean jj_3R_358()
+  private boolean jj_3R_363()
  {
     if (jj_scan_token(SUPER)) return true;
-    if (jj_3R_86()) return true;
-    if (jj_3R_85()) return true;
+    if (jj_3R_88()) return true;
+    if (jj_3R_87()) return true;
     return false;
   }
 
-  private boolean jj_3R_226()
+  private boolean jj_3R_227()
  {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_199()) return true;
+    if (jj_3R_200()) return true;
     return false;
   }
 
-  private boolean jj_3R_153()
+  private boolean jj_3R_154()
  {
     if (jj_scan_token(BOOLEAN)) return true;
     return false;
   }
 
-  private boolean jj_3R_357()
+  private boolean jj_3R_362()
  {
     if (jj_scan_token(EXTENDS)) return true;
-    if (jj_3R_86()) return true;
-    if (jj_3R_85()) return true;
+    if (jj_3R_88()) return true;
+    if (jj_3R_87()) return true;
     return false;
   }
 
-  private boolean jj_3R_342()
+  private boolean jj_3R_346()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_357()) {
+    if (jj_3R_362()) {
     jj_scanpos = xsp;
-    if (jj_3R_358()) return true;
+    if (jj_3R_363()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_97()
+  private boolean jj_3R_99()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_153()) {
-    jj_scanpos = xsp;
     if (jj_3R_154()) {
     jj_scanpos = xsp;
     if (jj_3R_155()) {
@@ -7019,7 +7244,9 @@
     jj_scanpos = xsp;
     if (jj_3R_159()) {
     jj_scanpos = xsp;
-    if (jj_3R_160()) return true;
+    if (jj_3R_160()) {
+    jj_scanpos = xsp;
+    if (jj_3R_161()) return true;
     }
     }
     }
@@ -7030,228 +7257,228 @@
     return false;
   }
 
-  private boolean jj_3R_121()
+  private boolean jj_3R_123()
  {
     if (jj_scan_token(LBRACE)) return true;
-    if (jj_3R_179()) return true;
+    if (jj_3R_180()) return true;
     if (jj_scan_token(RBRACE)) return true;
     return false;
   }
 
-  private boolean jj_3R_295()
+  private boolean jj_3R_298()
  {
     if (jj_scan_token(HOOK)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_342()) jj_scanpos = xsp;
+    if (jj_3R_346()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_107()
+  private boolean jj_3R_109()
  {
-    if (jj_3R_88()) return true;
+    if (jj_3R_90()) return true;
     if (jj_scan_token(COLON)) return true;
-    if (jj_3R_195()) return true;
+    if (jj_3R_196()) return true;
     return false;
   }
 
-  private boolean jj_3R_280()
+  private boolean jj_3R_283()
  {
     if (jj_scan_token(ASSERT)) return true;
-    if (jj_3R_90()) return true;
+    if (jj_3R_92()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_336()) jj_scanpos = xsp;
+    if (jj_3R_340()) jj_scanpos = xsp;
     if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
+  private boolean jj_3R_248()
+ {
+    if (jj_3R_298()) return true;
+    return false;
+  }
+
   private boolean jj_3R_247()
  {
-    if (jj_3R_295()) return true;
+    if (jj_3R_77()) return true;
     return false;
   }
 
-  private boolean jj_3R_246()
+  private boolean jj_3R_243()
  {
-    if (jj_3R_75()) return true;
+    if (jj_3R_296()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_200()
+ {
+    if (jj_3R_88()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_247()) {
+    jj_scanpos = xsp;
+    if (jj_3R_248()) return true;
+    }
     return false;
   }
 
   private boolean jj_3R_242()
  {
-    if (jj_3R_293()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_199()
- {
-    if (jj_3R_86()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_246()) {
-    jj_scanpos = xsp;
-    if (jj_3R_247()) return true;
-    }
+    if (jj_3R_295()) return true;
     return false;
   }
 
   private boolean jj_3R_241()
  {
-    if (jj_3R_292()) return true;
+    if (jj_3R_294()) return true;
     return false;
   }
 
   private boolean jj_3R_240()
  {
-    if (jj_3R_291()) return true;
+    if (jj_3R_293()) return true;
     return false;
   }
 
   private boolean jj_3R_239()
  {
-    if (jj_3R_290()) return true;
+    if (jj_3R_292()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_137()
+ {
+    if (jj_3R_200()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_227()) { jj_scanpos = xsp; break; }
+    }
     return false;
   }
 
   private boolean jj_3R_238()
  {
-    if (jj_3R_289()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_136()
- {
-    if (jj_3R_199()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_226()) { jj_scanpos = xsp; break; }
-    }
+    if (jj_3R_291()) return true;
     return false;
   }
 
   private boolean jj_3R_237()
  {
-    if (jj_3R_288()) return true;
+    if (jj_3R_290()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_89()
+ {
+    if (jj_scan_token(LT)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_137()) jj_scanpos = xsp;
+    if (jj_scan_token(GT)) return true;
     return false;
   }
 
   private boolean jj_3R_236()
  {
-    if (jj_3R_287()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_87()
- {
-    if (jj_scan_token(LT)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_136()) jj_scanpos = xsp;
-    if (jj_scan_token(GT)) return true;
+    if (jj_3R_289()) return true;
     return false;
   }
 
   private boolean jj_3R_235()
  {
-    if (jj_3R_286()) return true;
+    if (jj_3R_288()) return true;
     return false;
   }
 
   private boolean jj_3R_234()
  {
-    if (jj_3R_285()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_233()
- {
-    if (jj_3R_284()) return true;
+    if (jj_3R_287()) return true;
     return false;
   }
 
   private boolean jj_3_22()
  {
-    if (jj_3R_87()) return true;
+    if (jj_3R_89()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_233()
+ {
+    if (jj_3R_286()) return true;
     return false;
   }
 
   private boolean jj_3R_232()
  {
-    if (jj_3R_283()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_231()
- {
-    if (jj_3R_282()) return true;
+    if (jj_3R_285()) return true;
     return false;
   }
 
   private boolean jj_3_21()
  {
     if (jj_scan_token(DOT)) return true;
-    if (jj_3R_86()) return true;
     if (jj_3R_88()) return true;
+    if (jj_3R_90()) return true;
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3_22()) jj_scanpos = xsp;
     return false;
   }
 
+  private boolean jj_3R_231()
+ {
+    if (jj_3R_284()) return true;
+    return false;
+  }
+
   private boolean jj_3R_230()
  {
-    if (jj_3R_281()) return true;
+    if (jj_3R_123()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_406()
+ {
+    if (jj_scan_token(THROWS)) return true;
+    if (jj_3R_250()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_416()) { jj_scanpos = xsp; break; }
+    }
     return false;
   }
 
   private boolean jj_3R_229()
  {
-    if (jj_3R_121()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_393()
- {
-    if (jj_scan_token(THROWS)) return true;
-    if (jj_3R_249()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_403()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_228()
- {
-    if (jj_3R_280()) return true;
+    if (jj_3R_283()) return true;
     return false;
   }
 
   private boolean jj_3_19()
  {
-    if (jj_3R_86()) return true;
+    if (jj_3R_88()) return true;
     if (jj_scan_token(LBRACKET)) return true;
     return false;
   }
 
   private boolean jj_3_41()
  {
-    if (jj_3R_107()) return true;
+    if (jj_3R_109()) return true;
     return false;
   }
 
   private boolean jj_3_20()
  {
-    if (jj_3R_87()) return true;
+    if (jj_3R_89()) return true;
     return false;
   }
 
-  private boolean jj_3R_197()
+  private boolean jj_3R_198()
  {
-    if (jj_3R_88()) return true;
+    if (jj_3R_90()) return true;
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3_20()) jj_scanpos = xsp;
@@ -7262,14 +7489,12 @@
     return false;
   }
 
-  private boolean jj_3R_195()
+  private boolean jj_3R_196()
  {
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3_41()) {
     jj_scanpos = xsp;
-    if (jj_3R_228()) {
-    jj_scanpos = xsp;
     if (jj_3R_229()) {
     jj_scanpos = xsp;
     if (jj_3R_230()) {
@@ -7296,7 +7521,9 @@
     jj_scanpos = xsp;
     if (jj_3R_241()) {
     jj_scanpos = xsp;
-    if (jj_3R_242()) return true;
+    if (jj_3R_242()) {
+    jj_scanpos = xsp;
+    if (jj_3R_243()) return true;
     }
     }
     }
@@ -7317,60 +7544,60 @@
 
   private boolean jj_3_18()
  {
-    if (jj_3R_86()) return true;
+    if (jj_3R_88()) return true;
     if (jj_scan_token(LBRACKET)) return true;
     return false;
   }
 
-  private boolean jj_3R_198()
+  private boolean jj_3R_199()
  {
-    if (jj_3R_119()) return true;
+    if (jj_3R_121()) return true;
     return false;
   }
 
-  private boolean jj_3R_306()
+  private boolean jj_3R_310()
  {
-    if (jj_3R_86()) return true;
-    if (jj_3R_197()) return true;
+    if (jj_3R_88()) return true;
+    if (jj_3R_198()) return true;
     return false;
   }
 
   private boolean jj_3_39()
  {
-    if (jj_3R_105()) return true;
+    if (jj_3R_107()) return true;
     return false;
   }
 
-  private boolean jj_3R_196()
+  private boolean jj_3R_197()
  {
-    if (jj_3R_119()) return true;
+    if (jj_3R_121()) return true;
     return false;
   }
 
-  private boolean jj_3R_106()
+  private boolean jj_3R_108()
  {
-    if (jj_3R_90()) return true;
+    if (jj_3R_92()) return true;
     return false;
   }
 
-  private boolean jj_3R_341()
+  private boolean jj_3R_345()
  {
-    if (jj_3R_180()) return true;
+    if (jj_3R_181()) return true;
     return false;
   }
 
   private boolean jj_3_40()
  {
-    if (jj_3R_86()) return true;
+    if (jj_3R_88()) return true;
     if (jj_scan_token(LBRACKET)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_106()) jj_scanpos = xsp;
+    if (jj_3R_108()) jj_scanpos = xsp;
     if (jj_scan_token(RBRACKET)) return true;
     return false;
   }
 
-  private boolean jj_3R_313()
+  private boolean jj_3R_317()
  {
     Token xsp;
     if (jj_3_40()) return true;
@@ -7379,244 +7606,126 @@
       if (jj_3_40()) { jj_scanpos = xsp; break; }
     }
     xsp = jj_scanpos;
-    if (jj_3R_341()) jj_scanpos = xsp;
+    if (jj_3R_345()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_308()
+  private boolean jj_3_58()
+ {
+    if (jj_3R_86()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_312()
  {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_90()) return true;
+    if (jj_3R_92()) return true;
     return false;
   }
 
-  private boolean jj_3R_316()
+  private boolean jj_3R_319()
  {
-    if (jj_3R_183()) return true;
+    if (jj_3R_184()) return true;
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3_39()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_315()
+  private boolean jj_3R_318()
  {
-    if (jj_3R_313()) return true;
+    if (jj_3R_317()) return true;
     return false;
   }
 
-  private boolean jj_3R_119()
+  private boolean jj_3R_121()
  {
-    if (jj_3R_86()) return true;
+    if (jj_3R_88()) return true;
     if (jj_scan_token(LBRACKET)) return true;
     if (jj_scan_token(RBRACKET)) return true;
     return false;
   }
 
-  private boolean jj_3R_314()
+  private boolean jj_3R_282()
  {
-    if (jj_3R_87()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_279()
- {
+    if (jj_3R_198()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_314()) jj_scanpos = xsp;
-    if (jj_3R_306()) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_315()) {
+    if (jj_3R_318()) {
     jj_scanpos = xsp;
-    if (jj_3R_316()) return true;
+    if (jj_3R_319()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_278()
+  private boolean jj_3R_281()
  {
-    if (jj_3R_97()) return true;
-    if (jj_3R_313()) return true;
+    if (jj_3R_99()) return true;
+    if (jj_3R_317()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_135()
+ {
+    if (jj_3R_198()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_199()) { jj_scanpos = xsp; break; }
+    }
     return false;
   }
 
   private boolean jj_3R_134()
  {
+    if (jj_3R_99()) return true;
+    Token xsp;
     if (jj_3R_197()) return true;
-    Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_198()) { jj_scanpos = xsp; break; }
+      if (jj_3R_197()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_133()
+  private boolean jj_3R_280()
  {
-    if (jj_3R_97()) return true;
-    Token xsp;
-    if (jj_3R_196()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_196()) { jj_scanpos = xsp; break; }
-    }
+    if (jj_3R_89()) return true;
     return false;
   }
 
-  private boolean jj_3R_85()
+  private boolean jj_3R_451()
+ {
+    if (jj_3R_452()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_87()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_133()) {
+    if (jj_3R_134()) {
     jj_scanpos = xsp;
-    if (jj_3R_134()) return true;
+    if (jj_3R_135()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_222()
+  private boolean jj_3R_223()
  {
     if (jj_scan_token(NEW)) return true;
-    if (jj_3R_86()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_278()) {
+    if (jj_3R_280()) jj_scanpos = xsp;
+    if (jj_3R_88()) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_281()) {
     jj_scanpos = xsp;
-    if (jj_3R_279()) return true;
+    if (jj_3R_282()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_118()
- {
-    if (jj_3R_97()) return true;
-    return false;
-  }
-
-  private boolean jj_3_17()
- {
-    if (jj_3R_85()) return true;
-    return false;
-  }
-
-  private boolean jj_3_58()
- {
-    if (jj_3R_84()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_75()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3_17()) {
-    jj_scanpos = xsp;
-    if (jj_3R_118()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_264()
- {
-    if (jj_3R_90()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_308()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_214()
- {
-    if (jj_3R_264()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_120()
- {
-    if (jj_scan_token(STATIC)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_183()
- {
-    if (jj_scan_token(LPAREN)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_214()) jj_scanpos = xsp;
-    if (jj_scan_token(RPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_77()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_120()) jj_scanpos = xsp;
-    if (jj_3R_121()) return true;
-    return false;
-  }
-
-  private boolean jj_3_16()
- {
-    if (jj_3R_84()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_179()
- {
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3_16()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3_14()
- {
-    if (jj_3R_82()) return true;
-    if (jj_scan_token(DOT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_340()
- {
-    if (jj_scan_token(FALSE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_310()
- {
-    if (jj_scan_token(NULL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_339()
- {
-    if (jj_scan_token(TRUE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_441()
- {
-    if (jj_3R_442()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_83()
- {
-    if (jj_3R_87()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_185()
- {
-    if (jj_3R_87()) return true;
-    return false;
-  }
-
   private boolean jj_3_57()
  {
     if (jj_scan_token(REQUIRES)) return true;
@@ -7625,260 +7734,175 @@
     return false;
   }
 
-  private boolean jj_3_15()
+  private boolean jj_3R_120()
  {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_83()) jj_scanpos = xsp;
-    if (jj_scan_token(THIS)) return true;
-    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_99()) return true;
     return false;
   }
 
-  private boolean jj_3R_184()
- {
-    if (jj_3R_82()) return true;
-    if (jj_scan_token(DOT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_309()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_339()) {
-    jj_scanpos = xsp;
-    if (jj_3R_340()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_127()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_184()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_185()) jj_scanpos = xsp;
-    if (jj_scan_token(SUPER)) return true;
-    if (jj_3R_183()) return true;
-    if (jj_scan_token(SEMICOLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_271()
- {
-    if (jj_3R_310()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_182()
+  private boolean jj_3_17()
  {
     if (jj_3R_87()) return true;
     return false;
   }
 
-  private boolean jj_3R_270()
- {
-    if (jj_3R_309()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_126()
+  private boolean jj_3R_77()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_182()) jj_scanpos = xsp;
-    if (jj_scan_token(THIS)) return true;
-    if (jj_3R_183()) return true;
-    if (jj_scan_token(SEMICOLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_269()
- {
-    if (jj_scan_token(STRING_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_268()
- {
-    if (jj_scan_token(CHARACTER_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_81()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_126()) {
+    if (jj_3_17()) {
     jj_scanpos = xsp;
-    if (jj_3R_127()) return true;
+    if (jj_3R_120()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_267()
- {
-    if (jj_scan_token(FLOATING_POINT_LITERAL)) return true;
-    return false;
-  }
-
   private boolean jj_3R_266()
  {
-    if (jj_scan_token(LONG_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3_13()
- {
-    if (jj_3R_81()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_265()
- {
-    if (jj_scan_token(INTEGER_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_104()
- {
-    if (jj_3R_87()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_164()
- {
-    if (jj_3R_86()) return true;
-    if (jj_scan_token(ELLIPSIS)) return true;
-    return false;
-  }
-
-  private boolean jj_3_38()
- {
+    if (jj_3R_92()) return true;
     Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_104()) jj_scanpos = xsp;
-    if (jj_3R_74()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_394()
- {
-    if (jj_3R_81()) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_312()) { jj_scanpos = xsp; break; }
+    }
     return false;
   }
 
   private boolean jj_3R_215()
  {
+    if (jj_3R_266()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_122()
+ {
+    if (jj_scan_token(STATIC)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_184()
+ {
+    if (jj_scan_token(LPAREN)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_265()) {
-    jj_scanpos = xsp;
-    if (jj_3R_266()) {
-    jj_scanpos = xsp;
-    if (jj_3R_267()) {
-    jj_scanpos = xsp;
-    if (jj_3R_268()) {
-    jj_scanpos = xsp;
-    if (jj_3R_269()) {
-    jj_scanpos = xsp;
-    if (jj_3R_270()) {
-    jj_scanpos = xsp;
-    if (jj_3R_271()) return true;
-    }
-    }
-    }
-    }
-    }
+    if (jj_3R_215()) jj_scanpos = xsp;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_79()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_122()) jj_scanpos = xsp;
+    if (jj_3R_123()) return true;
+    return false;
+  }
+
+  private boolean jj_3_16()
+ {
+    if (jj_3R_86()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_180()
+ {
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_16()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_442()
+  private boolean jj_3_14()
+ {
+    if (jj_3R_84()) return true;
+    if (jj_scan_token(DOT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_344()
+ {
+    if (jj_scan_token(FALSE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_314()
+ {
+    if (jj_scan_token(NULL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_343()
+ {
+    if (jj_scan_token(TRUE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_452()
  {
     if (jj_scan_token(_DEFAULT)) return true;
-    if (jj_3R_114()) return true;
+    if (jj_3R_116()) return true;
     return false;
   }
 
-  private boolean jj_3R_163()
+  private boolean jj_3R_85()
  {
-    if (jj_scan_token(LBRACKET)) return true;
-    if (jj_3R_90()) return true;
-    if (jj_scan_token(RBRACKET)) return true;
+    if (jj_3R_89()) return true;
     return false;
   }
 
-  private boolean jj_3R_254()
+  private boolean jj_3R_186()
  {
-    if (jj_3R_183()) return true;
+    if (jj_3R_89()) return true;
     return false;
   }
 
-  private boolean jj_3R_403()
- {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_249()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_224()
- {
-    if (jj_3R_74()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_253()
- {
-    if (jj_3R_87()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_365()
- {
-    if (jj_3R_117()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_353()
+  private boolean jj_3_15()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_365()) jj_scanpos = xsp;
-    if (jj_3R_88()) return true;
-    if (jj_3R_392()) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_393()) jj_scanpos = xsp;
-    if (jj_scan_token(LBRACE)) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_394()) jj_scanpos = xsp;
-    if (jj_3R_179()) return true;
-    if (jj_scan_token(RBRACE)) return true;
+    if (jj_3R_85()) jj_scanpos = xsp;
+    if (jj_scan_token(THIS)) return true;
+    if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_205()
+  private boolean jj_3R_185()
+ {
+    if (jj_3R_84()) return true;
+    if (jj_scan_token(DOT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_313()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_253()) jj_scanpos = xsp;
-    if (jj_3R_88()) return true;
+    if (jj_3R_343()) {
+    jj_scanpos = xsp;
+    if (jj_3R_344()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_128()
+ {
+    Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_254()) jj_scanpos = xsp;
+    if (jj_3R_185()) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_186()) jj_scanpos = xsp;
+    if (jj_scan_token(SUPER)) return true;
+    if (jj_3R_184()) return true;
+    if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
-  private boolean jj_3R_204()
+  private boolean jj_3R_273()
  {
-    if (jj_3R_222()) return true;
-    return false;
-  }
-
-  private boolean jj_3_12()
- {
-    if (jj_3R_80()) return true;
+    if (jj_3R_314()) return true;
     return false;
   }
 
@@ -7888,341 +7912,384 @@
     return false;
   }
 
-  private boolean jj_3R_203()
+  private boolean jj_3R_183()
  {
-    if (jj_scan_token(THIS)) return true;
+    if (jj_3R_89()) return true;
     return false;
   }
 
-  private boolean jj_3R_439()
+  private boolean jj_3R_272()
  {
-    if (jj_3R_75()) return true;
-    if (jj_3R_88()) return true;
+    if (jj_3R_313()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_449()
+ {
+    if (jj_3R_77()) return true;
+    if (jj_3R_90()) return true;
     if (jj_scan_token(LPAREN)) return true;
     if (jj_scan_token(RPAREN)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_441()) jj_scanpos = xsp;
+    if (jj_3R_451()) jj_scanpos = xsp;
     if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
+  private boolean jj_3R_127()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_183()) jj_scanpos = xsp;
+    if (jj_scan_token(THIS)) return true;
+    if (jj_3R_184()) return true;
+    if (jj_scan_token(SEMICOLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_271()
+ {
+    if (jj_scan_token(STRING_LITERAL)) return true;
+    return false;
+  }
+
   private boolean jj_3_55()
  {
-    if (jj_3R_75()) return true;
-    if (jj_3R_74()) return true;
+    if (jj_3R_77()) return true;
+    if (jj_3R_76()) return true;
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_438()
+  private boolean jj_3R_448()
  {
-    if (jj_3R_354()) return true;
+    if (jj_3R_359()) return true;
     return false;
   }
 
-  private boolean jj_3R_437()
+  private boolean jj_3R_447()
  {
-    if (jj_3R_352()) return true;
+    if (jj_3R_357()) return true;
     return false;
   }
 
-  private boolean jj_3R_436()
+  private boolean jj_3R_270()
  {
-    if (jj_3R_351()) return true;
+    if (jj_scan_token(CHARACTER_LITERAL)) return true;
     return false;
   }
 
-  private boolean jj_3R_181()
+  private boolean jj_3R_446()
  {
-    if (jj_3R_80()) return true;
-    if (jj_scan_token(DOT)) return true;
+    if (jj_3R_356()) return true;
     return false;
   }
 
-  private boolean jj_3R_162()
+  private boolean jj_3R_445()
  {
-    if (jj_scan_token(DOT)) return true;
+    if (jj_3R_195()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_83()
+ {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_203()) {
+    if (jj_3R_127()) {
     jj_scanpos = xsp;
-    if (jj_3R_204()) {
-    jj_scanpos = xsp;
-    if (jj_3R_205()) return true;
-    }
+    if (jj_3R_128()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_435()
+  private boolean jj_3R_269()
  {
-    if (jj_3R_194()) return true;
+    if (jj_scan_token(FLOATING_POINT_LITERAL)) return true;
     return false;
   }
 
-  private boolean jj_3R_124()
+  private boolean jj_3R_444()
  {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_181()) jj_scanpos = xsp;
-    if (jj_3R_86()) return true;
-    if (jj_scan_token(THIS)) return true;
+    if (jj_3R_449()) return true;
     return false;
   }
 
-  private boolean jj_3R_434()
+  private boolean jj_3R_268()
  {
-    if (jj_3R_439()) return true;
+    if (jj_scan_token(LONG_LITERAL)) return true;
     return false;
   }
 
   private boolean jj_3_54()
  {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_114()) return true;
+    if (jj_3R_116()) return true;
     return false;
   }
 
-  private boolean jj_3R_99()
+  private boolean jj_3_13()
+ {
+    if (jj_3R_83()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_267()
+ {
+    if (jj_scan_token(INTEGER_LITERAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_165()
+ {
+    if (jj_3R_88()) return true;
+    if (jj_scan_token(ELLIPSIS)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_106()
+ {
+    if (jj_3R_89()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_441()
+ {
+    if (jj_3R_110()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_444()) {
+    jj_scanpos = xsp;
+    if (jj_3R_445()) {
+    jj_scanpos = xsp;
+    if (jj_3R_446()) {
+    jj_scanpos = xsp;
+    if (jj_3R_447()) {
+    jj_scanpos = xsp;
+    if (jj_3R_448()) return true;
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_38()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_162()) {
-    jj_scanpos = xsp;
-    if (jj_3R_163()) return true;
-    }
+    if (jj_3R_106()) jj_scanpos = xsp;
+    if (jj_3R_76()) return true;
     return false;
   }
 
-  private boolean jj_3R_311()
+  private boolean jj_3R_407()
  {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_100()) return true;
+    if (jj_3R_83()) return true;
     return false;
   }
 
-  private boolean jj_3R_223()
- {
-    if (jj_3R_87()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_79()
- {
-    if (jj_3R_86()) return true;
-    if (jj_3R_75()) return true;
-    if (jj_3R_124()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_161()
- {
-    if (jj_scan_token(DOT)) return true;
-    if (jj_scan_token(SUPER)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_429()
- {
-    if (jj_3R_108()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_434()) {
-    jj_scanpos = xsp;
-    if (jj_3R_435()) {
-    jj_scanpos = xsp;
-    if (jj_3R_436()) {
-    jj_scanpos = xsp;
-    if (jj_3R_437()) {
-    jj_scanpos = xsp;
-    if (jj_3R_438()) return true;
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3_37()
- {
-    if (jj_3R_99()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_417()
- {
-    if (jj_3R_429()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_401()
+  private boolean jj_3R_216()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_417()) {
+    if (jj_3R_267()) {
+    jj_scanpos = xsp;
+    if (jj_3R_268()) {
+    jj_scanpos = xsp;
+    if (jj_3R_269()) {
+    jj_scanpos = xsp;
+    if (jj_3R_270()) {
+    jj_scanpos = xsp;
+    if (jj_3R_271()) {
+    jj_scanpos = xsp;
+    if (jj_3R_272()) {
+    jj_scanpos = xsp;
+    if (jj_3R_273()) return true;
+    }
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_164()
+ {
+    if (jj_scan_token(LBRACKET)) return true;
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(RBRACKET)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_430()
+ {
+    if (jj_3R_441()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_414()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_430()) {
     jj_scanpos = xsp;
     if (jj_scan_token(98)) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_275()
+  private boolean jj_3R_256()
  {
-    if (jj_3R_74()) return true;
+    if (jj_3R_184()) return true;
     return false;
   }
 
-  private boolean jj_3R_98()
+  private boolean jj_3R_416()
  {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3_37()) {
-    jj_scanpos = xsp;
-    if (jj_3R_161()) return true;
-    }
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_250()) return true;
     return false;
   }
 
   private boolean jj_3R_225()
  {
-    if (jj_3R_183()) return true;
+    if (jj_3R_76()) return true;
     return false;
   }
 
-  private boolean jj_3R_391()
+  private boolean jj_3R_255()
+ {
+    if (jj_3R_89()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_374()
+ {
+    if (jj_3R_119()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_404()
  {
     if (jj_scan_token(LBRACE)) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_401()) { jj_scanpos = xsp; break; }
+      if (jj_3R_414()) { jj_scanpos = xsp; break; }
     }
     if (jj_scan_token(RBRACE)) return true;
     return false;
   }
 
-  private boolean jj_3R_193()
+  private boolean jj_3R_358()
  {
-    if (jj_3R_88()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_225()) jj_scanpos = xsp;
+    if (jj_3R_374()) jj_scanpos = xsp;
+    if (jj_3R_90()) return true;
+    if (jj_3R_405()) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_406()) jj_scanpos = xsp;
+    if (jj_scan_token(LBRACE)) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_407()) jj_scanpos = xsp;
+    if (jj_3R_180()) return true;
+    if (jj_scan_token(RBRACE)) return true;
     return false;
   }
 
-  private boolean jj_3R_100()
+  private boolean jj_3R_206()
  {
-    if (jj_3R_108()) return true;
-    if (jj_3R_75()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_164()) jj_scanpos = xsp;
-    if (jj_3R_101()) return true;
+    if (jj_3R_255()) jj_scanpos = xsp;
+    if (jj_3R_90()) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_256()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3_36()
+  private boolean jj_3R_205()
  {
-    if (jj_3R_103()) return true;
-    if (jj_scan_token(DOUBLECOLON)) return true;
+    if (jj_3R_223()) return true;
     return false;
   }
 
-  private boolean jj_3_35()
+  private boolean jj_3_12()
  {
-    if (jj_3R_102()) return true;
+    if (jj_3R_82()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_204()
+ {
+    if (jj_scan_token(THIS)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_182()
+ {
+    if (jj_3R_82()) return true;
     if (jj_scan_token(DOT)) return true;
-    if (jj_scan_token(CLASS)) return true;
     return false;
   }
 
-  private boolean jj_3R_312()
+  private boolean jj_3R_163()
  {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_101()) return true;
+    if (jj_scan_token(DOT)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_204()) {
+    jj_scanpos = xsp;
+    if (jj_3R_205()) {
+    jj_scanpos = xsp;
+    if (jj_3R_206()) return true;
+    }
+    }
     return false;
   }
 
-  private boolean jj_3R_352()
+  private boolean jj_3R_357()
  {
     if (jj_scan_token(AT)) return true;
     if (jj_scan_token(INTERFACE)) return true;
-    if (jj_3R_88()) return true;
-    if (jj_3R_391()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_192()
- {
-    if (jj_3R_103()) return true;
-    if (jj_scan_token(DOUBLECOLON)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_223()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_224()) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(42)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3_34()
- {
-    if (jj_3R_101()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_277()
- {
-    if (jj_3R_101()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_312()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_191()
- {
-    if (jj_3R_102()) return true;
-    if (jj_scan_token(DOT)) return true;
-    if (jj_scan_token(CLASS)) return true;
-    return false;
-  }
-
-  private boolean jj_3_33()
- {
-    if (jj_3R_100()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_190()
- {
-    if (jj_3R_222()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_346()
- {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_345()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_221()
- {
     if (jj_3R_90()) return true;
-    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_404()) return true;
     return false;
   }
 
-  private boolean jj_3R_362()
+  private boolean jj_3R_126()
  {
-    if (jj_3R_114()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_182()) jj_scanpos = xsp;
+    if (jj_scan_token(THIS)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_350()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_349()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_101()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_163()) {
+    jj_scanpos = xsp;
+    if (jj_3R_164()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_367()
+ {
+    if (jj_3R_116()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
@@ -8231,116 +8298,55 @@
     return false;
   }
 
-  private boolean jj_3R_274()
- {
-    if (jj_3R_87()) return true;
-    return false;
-  }
-
-  private boolean jj_3_10()
+  private boolean jj_3R_315()
  {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_78()) return true;
+    if (jj_3R_102()) return true;
     return false;
   }
 
-  private boolean jj_3R_220()
+  private boolean jj_3R_224()
  {
-    if (jj_3R_277()) return true;
-    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_89()) return true;
     return false;
   }
 
-  private boolean jj_3R_276()
+  private boolean jj_3R_81()
  {
-    if (jj_3R_100()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_311()) { jj_scanpos = xsp; break; }
-    }
+    if (jj_3R_88()) return true;
+    if (jj_3R_77()) return true;
+    if (jj_3R_126()) return true;
     return false;
   }
 
-  private boolean jj_3R_218()
+  private boolean jj_3R_162()
  {
-    if (jj_scan_token(RPAREN)) return true;
+    if (jj_scan_token(DOT)) return true;
+    if (jj_scan_token(SUPER)) return true;
     return false;
   }
 
-  private boolean jj_3_11()
- {
-    if (jj_3R_79()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_219()
- {
-    if (jj_3R_276()) return true;
-    if (jj_scan_token(RPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_212()
+  private boolean jj_3R_213()
  {
     if (jj_scan_token(LBRACE)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_362()) jj_scanpos = xsp;
+    if (jj_3R_367()) jj_scanpos = xsp;
     xsp = jj_scanpos;
     if (jj_scan_token(99)) jj_scanpos = xsp;
     if (jj_scan_token(RBRACE)) return true;
     return false;
   }
 
-  private boolean jj_3R_217()
+  private boolean jj_3_37()
  {
-    if (jj_scan_token(DOUBLECOLON)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_274()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_275()) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(42)) return true;
-    }
+    if (jj_3R_101()) return true;
     return false;
   }
 
-  private boolean jj_3R_420()
+  private boolean jj_3R_177()
  {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_100()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_419()
- {
-    if (jj_3R_100()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_189()
- {
-    if (jj_scan_token(LPAREN)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_218()) {
-    jj_scanpos = xsp;
-    if (jj_3R_219()) {
-    jj_scanpos = xsp;
-    if (jj_3R_220()) {
-    jj_scanpos = xsp;
-    if (jj_3R_221()) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_176()
- {
-    if (jj_3R_149()) return true;
+    if (jj_3R_150()) return true;
     return false;
   }
 
@@ -8350,157 +8356,483 @@
     return false;
   }
 
+  private boolean jj_3R_176()
+ {
+    if (jj_3R_213()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_277()
+ {
+    if (jj_3R_76()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_100()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_37()) {
+    jj_scanpos = xsp;
+    if (jj_3R_162()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_226()
+ {
+    if (jj_3R_184()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_102()
+ {
+    if (jj_3R_110()) return true;
+    if (jj_3R_77()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_165()) jj_scanpos = xsp;
+    if (jj_3R_103()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_194()
+ {
+    if (jj_3R_90()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_226()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3_36()
+ {
+    if (jj_3R_105()) return true;
+    if (jj_scan_token(DOUBLECOLON)) return true;
+    return false;
+  }
+
   private boolean jj_3R_175()
  {
-    if (jj_3R_212()) return true;
+    if (jj_3R_117()) return true;
     return false;
   }
 
-  private boolean jj_3R_396()
- {
-    if (jj_3R_119()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_418()
- {
-    if (jj_3R_79()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_402()
+  private boolean jj_3R_116()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_418()) {
+    if (jj_3R_175()) {
     jj_scanpos = xsp;
-    if (jj_3R_419()) return true;
+    if (jj_3R_176()) {
+    jj_scanpos = xsp;
+    if (jj_3R_177()) return true;
     }
+    }
+    return false;
+  }
+
+  private boolean jj_3_35()
+ {
+    if (jj_3R_104()) return true;
+    if (jj_scan_token(DOT)) return true;
+    if (jj_scan_token(CLASS)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_316()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_103()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_349()
+ {
+    if (jj_3R_90()) return true;
+    if (jj_scan_token(ASSIGN)) return true;
+    if (jj_3R_116()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_193()
+ {
+    if (jj_3R_105()) return true;
+    if (jj_scan_token(DOUBLECOLON)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_224()) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_225()) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(42)) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_279()
+ {
+    if (jj_3R_103()) return true;
+    Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_420()) { jj_scanpos = xsp; break; }
+      if (jj_3R_316()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_273()
+  private boolean jj_3_34()
  {
-    if (jj_3R_183()) return true;
+    if (jj_3R_103()) return true;
+    if (jj_scan_token(COMMA)) return true;
     return false;
   }
 
-  private boolean jj_3R_174()
+  private boolean jj_3R_192()
  {
-    if (jj_3R_115()) return true;
+    if (jj_3R_104()) return true;
+    if (jj_scan_token(DOT)) return true;
+    if (jj_scan_token(CLASS)) return true;
     return false;
   }
 
-  private boolean jj_3R_392()
+  private boolean jj_3_33()
  {
-    if (jj_scan_token(LPAREN)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_402()) jj_scanpos = xsp;
+    if (jj_3R_102()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_191()
+ {
+    if (jj_3R_223()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_222()
+ {
+    if (jj_3R_92()) return true;
     if (jj_scan_token(RPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_216()
+  private boolean jj_3R_115()
+ {
+    if (jj_3R_76()) return true;
+    if (jj_scan_token(ASSIGN)) return true;
+    return false;
+  }
+
+  private boolean jj_3_52()
+ {
+    if (jj_scan_token(LPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_326()
+ {
+    if (jj_3R_349()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_350()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_10()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_80()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_276()
+ {
+    if (jj_3R_89()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_278()
+ {
+    if (jj_3R_102()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_315()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_221()
+ {
+    if (jj_3R_279()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3_11()
+ {
+    if (jj_3R_81()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_219()
+ {
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3_51()
+ {
+    if (jj_scan_token(LPAREN)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_115()) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(93)) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_220()
+ {
+    if (jj_3R_278()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_246()
+ {
+    return false;
+  }
+
+  private boolean jj_3R_297()
+ {
+    if (jj_3R_326()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_218()
+ {
+    if (jj_scan_token(DOUBLECOLON)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_276()) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_277()) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(42)) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_433()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_102()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_432()
+ {
+    if (jj_3R_102()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_190()
+ {
+    if (jj_scan_token(LPAREN)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_219()) {
+    jj_scanpos = xsp;
+    if (jj_3R_220()) {
+    jj_scanpos = xsp;
+    if (jj_3R_221()) {
+    jj_scanpos = xsp;
+    if (jj_3R_222()) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_245()
+ {
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_116()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_409()
+ {
+    if (jj_3R_121()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_431()
+ {
+    if (jj_3R_81()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_244()
+ {
+    if (jj_scan_token(LPAREN)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_297()) jj_scanpos = xsp;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_415()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_431()) {
+    jj_scanpos = xsp;
+    if (jj_3R_432()) return true;
+    }
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_433()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_275()
+ {
+    if (jj_3R_184()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_117()
+ {
+    if (jj_scan_token(AT)) return true;
+    if (jj_3R_82()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_244()) {
+    jj_scanpos = xsp;
+    if (jj_3R_245()) {
+    jj_scanpos = xsp;
+    if (jj_3R_246()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_405()
+ {
+    if (jj_scan_token(LPAREN)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_415()) jj_scanpos = xsp;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_217()
  {
     if (jj_scan_token(DOT)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_272()) jj_scanpos = xsp;
-    if (jj_3R_88()) return true;
+    if (jj_3R_274()) jj_scanpos = xsp;
+    if (jj_3R_90()) return true;
     xsp = jj_scanpos;
-    if (jj_3R_273()) jj_scanpos = xsp;
+    if (jj_3R_275()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_272()
+  private boolean jj_3R_274()
  {
-    if (jj_3R_87()) return true;
+    if (jj_3R_89()) return true;
     return false;
   }
 
-  private boolean jj_3R_114()
+  private boolean jj_3_50()
  {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_174()) {
-    jj_scanpos = xsp;
-    if (jj_3R_175()) {
-    jj_scanpos = xsp;
-    if (jj_3R_176()) return true;
-    }
-    }
+    if (jj_scan_token(AT)) return true;
     return false;
   }
 
   private boolean jj_3_32()
  {
-    if (jj_3R_99()) return true;
+    if (jj_3R_101()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_189()
+ {
+    if (jj_scan_token(SUPER)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_217()) {
+    jj_scanpos = xsp;
+    if (jj_3R_218()) return true;
+    }
     return false;
   }
 
   private boolean jj_3R_188()
  {
-    if (jj_scan_token(SUPER)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_216()) {
-    jj_scanpos = xsp;
-    if (jj_3R_217()) return true;
-    }
+    if (jj_scan_token(THIS)) return true;
     return false;
   }
 
   private boolean jj_3R_187()
  {
-    if (jj_scan_token(THIS)) return true;
+    if (jj_3R_216()) return true;
     return false;
   }
 
-  private boolean jj_3R_345()
+  private boolean jj_3R_105()
  {
     if (jj_3R_88()) return true;
-    if (jj_scan_token(ASSIGN)) return true;
-    if (jj_3R_114()) return true;
+    if (jj_3R_77()) return true;
     return false;
   }
 
-  private boolean jj_3R_186()
+  private boolean jj_3R_136()
  {
-    if (jj_3R_215()) return true;
+    if (jj_3R_117()) return true;
     return false;
   }
 
-  private boolean jj_3R_103()
+  private boolean jj_3R_88()
  {
-    if (jj_3R_86()) return true;
-    if (jj_3R_75()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_136()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_130()
+ {
+    if (jj_3R_101()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_151()
+ {
+    return false;
+  }
+
+  private boolean jj_3_48()
+ {
+    if (jj_scan_token(SEMICOLON)) return true;
+    if (jj_3R_113()) return true;
     return false;
   }
 
   private boolean jj_3R_129()
  {
-    if (jj_3R_99()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_113()
- {
-    if (jj_3R_74()) return true;
-    if (jj_scan_token(ASSIGN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_128()
- {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_186()) {
-    jj_scanpos = xsp;
     if (jj_3R_187()) {
     jj_scanpos = xsp;
     if (jj_3R_188()) {
@@ -8513,7 +8845,9 @@
     jj_scanpos = xsp;
     if (jj_3R_192()) {
     jj_scanpos = xsp;
-    if (jj_3R_193()) return true;
+    if (jj_3R_193()) {
+    jj_scanpos = xsp;
+    if (jj_3R_194()) return true;
     }
     }
     }
@@ -8524,139 +8858,103 @@
     return false;
   }
 
-  private boolean jj_3_52()
+  private boolean jj_3R_250()
  {
-    if (jj_scan_token(LPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_323()
- {
-    if (jj_3R_345()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_346()) { jj_scanpos = xsp; break; }
-    }
+    if (jj_3R_88()) return true;
+    if (jj_3R_87()) return true;
     return false;
   }
 
   private boolean jj_3_31()
  {
-    if (jj_3R_98()) return true;
+    if (jj_3R_100()) return true;
     return false;
   }
 
-  private boolean jj_3R_249()
- {
-    if (jj_3R_86()) return true;
-    if (jj_3R_85()) return true;
-    return false;
-  }
-
-  private boolean jj_3_51()
- {
-    if (jj_scan_token(LPAREN)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_113()) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(93)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_245()
+  private boolean jj_3R_152()
  {
     return false;
   }
 
-  private boolean jj_3R_294()
+  private boolean jj_3R_94()
  {
-    if (jj_3R_323()) return true;
+    jj_lookingAhead = true;
+    jj_semLA = getToken(1).kind == GT &&
+                getToken(1).realKind == RSIGNEDSHIFT;
+    jj_lookingAhead = false;
+    if (!jj_semLA || jj_3R_151()) return true;
+    if (jj_scan_token(GT)) return true;
+    if (jj_scan_token(GT)) return true;
     return false;
   }
 
-  private boolean jj_3R_244()
- {
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_114()) return true;
-    if (jj_scan_token(RPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_404()
+  private boolean jj_3R_417()
  {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_249()) return true;
+    if (jj_3R_250()) return true;
     return false;
   }
 
-  private boolean jj_3R_398()
+  private boolean jj_3R_411()
  {
-    if (jj_3R_121()) return true;
+    if (jj_3R_123()) return true;
     return false;
   }
 
-  private boolean jj_3R_243()
- {
-    if (jj_scan_token(LPAREN)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_294()) jj_scanpos = xsp;
-    if (jj_scan_token(RPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_397()
+  private boolean jj_3R_410()
  {
     if (jj_scan_token(THROWS)) return true;
-    if (jj_3R_249()) return true;
+    if (jj_3R_250()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_404()) { jj_scanpos = xsp; break; }
+      if (jj_3R_417()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_82()
+  private boolean jj_3R_95()
  {
-    if (jj_3R_128()) return true;
+    jj_lookingAhead = true;
+    jj_semLA = getToken(1).kind == GT &&
+                getToken(1).realKind == RUNSIGNEDSHIFT;
+    jj_lookingAhead = false;
+    if (!jj_semLA || jj_3R_152()) return true;
+    if (jj_scan_token(GT)) return true;
+    if (jj_scan_token(GT)) return true;
+    if (jj_scan_token(GT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_84()
+ {
+    if (jj_3R_129()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_129()) { jj_scanpos = xsp; break; }
+      if (jj_3R_130()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_366()
+  private boolean jj_3_49()
  {
-    if (jj_3R_117()) return true;
+    if (jj_3R_110()) return true;
+    if (jj_3R_77()) return true;
+    if (jj_3R_114()) return true;
     return false;
   }
 
-  private boolean jj_3R_115()
+  private boolean jj_3R_375()
  {
-    if (jj_scan_token(AT)) return true;
+    if (jj_3R_119()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_339()
+ {
     if (jj_3R_80()) return true;
     Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_243()) {
-    jj_scanpos = xsp;
-    if (jj_3R_244()) {
-    jj_scanpos = xsp;
-    if (jj_3R_245()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_335()
- {
-    if (jj_3R_78()) return true;
-    Token xsp;
     while (true) {
       xsp = jj_scanpos;
       if (jj_3_10()) { jj_scanpos = xsp; break; }
@@ -8664,38 +8962,38 @@
     return false;
   }
 
-  private boolean jj_3R_355()
+  private boolean jj_3R_360()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_366()) jj_scanpos = xsp;
-    if (jj_3R_86()) return true;
-    if (jj_3R_102()) return true;
+    if (jj_3R_375()) jj_scanpos = xsp;
     if (jj_3R_88()) return true;
-    if (jj_3R_392()) return true;
+    if (jj_3R_104()) return true;
+    if (jj_3R_90()) return true;
+    if (jj_3R_405()) return true;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_396()) { jj_scanpos = xsp; break; }
+      if (jj_3R_409()) { jj_scanpos = xsp; break; }
     }
     xsp = jj_scanpos;
-    if (jj_3R_397()) jj_scanpos = xsp;
+    if (jj_3R_410()) jj_scanpos = xsp;
     xsp = jj_scanpos;
-    if (jj_3R_398()) {
+    if (jj_3R_411()) {
     jj_scanpos = xsp;
     if (jj_scan_token(98)) return true;
     }
     return false;
   }
 
-  private boolean jj_3_50()
+  private boolean jj_3R_173()
  {
-    if (jj_scan_token(AT)) return true;
+    if (jj_3R_212()) return true;
     return false;
   }
 
-  private boolean jj_3R_211()
+  private boolean jj_3R_212()
  {
-    if (jj_3R_128()) return true;
+    if (jj_3R_129()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
@@ -8704,66 +9002,66 @@
     return false;
   }
 
-  private boolean jj_3R_165()
+  private boolean jj_3R_166()
  {
-    if (jj_3R_119()) return true;
+    if (jj_3R_121()) return true;
     return false;
   }
 
-  private boolean jj_3R_135()
+  private boolean jj_3R_172()
  {
-    if (jj_3R_115()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_86()
- {
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_135()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_150()
- {
-    return false;
-  }
-
-  private boolean jj_3R_201()
- {
-    if (jj_scan_token(BIT_AND)) return true;
-    if (jj_3R_249()) return true;
-    return false;
-  }
-
-  private boolean jj_3_48()
- {
-    if (jj_scan_token(SEMICOLON)) return true;
     if (jj_3R_111()) return true;
     return false;
   }
 
-  private boolean jj_3R_152()
+  private boolean jj_3R_113()
  {
-    if (jj_3R_85()) return true;
     Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_201()) { jj_scanpos = xsp; break; }
+    xsp = jj_scanpos;
+    if (jj_3R_172()) {
+    jj_scanpos = xsp;
+    if (jj_3R_173()) return true;
     }
-    if (jj_scan_token(RPAREN)) return true;
-    if (jj_3R_202()) return true;
     return false;
   }
 
-  private boolean jj_3R_180()
+  private boolean jj_3R_202()
+ {
+    if (jj_scan_token(BIT_AND)) return true;
+    if (jj_3R_250()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_377()
+ {
+    if (jj_3R_113()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_48()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_153()
+ {
+    if (jj_3R_87()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_202()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_203()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_181()
  {
     if (jj_scan_token(LBRACE)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_335()) jj_scanpos = xsp;
+    if (jj_3R_339()) jj_scanpos = xsp;
     xsp = jj_scanpos;
     if (jj_scan_token(99)) jj_scanpos = xsp;
     if (jj_scan_token(RBRACE)) return true;
@@ -8772,101 +9070,130 @@
 
   private boolean jj_3_30()
  {
-    if (jj_3R_97()) return true;
+    if (jj_3R_99()) return true;
     if (jj_scan_token(RPAREN)) return true;
-    if (jj_3R_170()) return true;
+    if (jj_3R_171()) return true;
     return false;
   }
 
-  private boolean jj_3R_151()
+  private boolean jj_3R_125()
  {
+    if (jj_3R_92()) return true;
     return false;
   }
 
-  private boolean jj_3R_123()
+  private boolean jj_3R_124()
  {
-    if (jj_3R_90()) return true;
+    if (jj_3R_181()) return true;
     return false;
   }
 
-  private boolean jj_3R_92()
- {
-    jj_lookingAhead = true;
-    jj_semLA = getToken(1).kind == GT &&
-                getToken(1).realKind == RSIGNEDSHIFT;
-    jj_lookingAhead = false;
-    if (!jj_semLA || jj_3R_150()) return true;
-    if (jj_scan_token(GT)) return true;
-    if (jj_scan_token(GT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_122()
- {
-    if (jj_3R_180()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_173()
+  private boolean jj_3R_174()
  {
     if (jj_scan_token(ASSIGN)) return true;
-    if (jj_3R_78()) return true;
+    if (jj_3R_80()) return true;
     return false;
   }
 
-  private boolean jj_3R_94()
+  private boolean jj_3R_437()
  {
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_86()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3_30()) {
-    jj_scanpos = xsp;
-    if (jj_3R_152()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_93()
- {
-    jj_lookingAhead = true;
-    jj_semLA = getToken(1).kind == GT &&
-                getToken(1).realKind == RUNSIGNEDSHIFT;
-    jj_lookingAhead = false;
-    if (!jj_semLA || jj_3R_151()) return true;
-    if (jj_scan_token(GT)) return true;
-    if (jj_scan_token(GT)) return true;
-    if (jj_scan_token(GT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_78()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_122()) {
-    jj_scanpos = xsp;
+    if (jj_scan_token(FINALLY)) return true;
     if (jj_3R_123()) return true;
-    }
     return false;
   }
 
-  private boolean jj_3_49()
+  private boolean jj_3R_423()
  {
-    if (jj_3R_108()) return true;
-    if (jj_3R_75()) return true;
-    if (jj_3R_112()) return true;
+    if (jj_scan_token(FINALLY)) return true;
+    if (jj_3R_123()) return true;
     return false;
   }
 
-  private boolean jj_3R_172()
+  private boolean jj_3_47()
  {
-    if (jj_3R_211()) return true;
+    if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
   private boolean jj_3R_96()
  {
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_88()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_30()) {
+    jj_scanpos = xsp;
+    if (jj_3R_153()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_348()
+ {
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_377()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_47()) jj_scanpos = xsp;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_80()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_124()) {
+    jj_scanpos = xsp;
+    if (jj_3R_125()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_443()
+ {
+    if (jj_scan_token(BIT_OR)) return true;
+    if (jj_3R_250()) return true;
+    return false;
+  }
+
+  private boolean jj_3_28()
+ {
+    if (jj_3R_96()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_254()
+ {
+    if (jj_3R_303()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_436()
+ {
+    if (jj_scan_token(CATCH)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_110()) return true;
+    if (jj_3R_87()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_443()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_3R_103()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_123()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_253()
+ {
+    if (jj_3R_302()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_98()
+ {
     if (jj_scan_token(DECR)) return true;
     return false;
   }
@@ -8875,145 +9202,140 @@
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_95()) {
+    if (jj_3R_97()) {
     jj_scanpos = xsp;
-    if (jj_3R_96()) return true;
+    if (jj_3R_98()) return true;
     }
     return false;
   }
 
-  private boolean jj_3R_95()
+  private boolean jj_3R_97()
  {
     if (jj_scan_token(INCR)) return true;
     return false;
   }
 
-  private boolean jj_3_28()
+  private boolean jj_3R_103()
  {
-    if (jj_3R_94()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_101()
- {
-    if (jj_3R_88()) return true;
+    if (jj_3R_90()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_165()) { jj_scanpos = xsp; break; }
+      if (jj_3R_166()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_76()
+  private boolean jj_3R_78()
  {
-    if (jj_3R_119()) return true;
+    if (jj_3R_121()) return true;
     return false;
   }
 
-  private boolean jj_3R_171()
+  private boolean jj_3R_301()
  {
-    if (jj_3R_109()) return true;
+    if (jj_scan_token(BANG)) return true;
     return false;
   }
 
-  private boolean jj_3R_111()
+  private boolean jj_3R_300()
  {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_171()) {
-    jj_scanpos = xsp;
-    if (jj_3R_172()) return true;
-    }
+    if (jj_scan_token(TILDE)) return true;
     return false;
   }
 
-  private boolean jj_3R_299()
+  private boolean jj_3R_302()
  {
-    if (jj_3R_211()) return true;
+    if (jj_3R_212()) return true;
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3_29()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_251()
+  private boolean jj_3R_252()
  {
-    if (jj_3R_94()) return true;
+    if (jj_3R_96()) return true;
     return false;
   }
 
-  private boolean jj_3R_368()
+  private boolean jj_3R_251()
  {
-    if (jj_3R_111()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_300()) {
+    jj_scanpos = xsp;
+    if (jj_3R_301()) return true;
+    }
+    if (jj_3R_171()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_114()
+ {
+    if (jj_3R_103()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_174()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_422()
+ {
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3_48()) { jj_scanpos = xsp; break; }
+      if (jj_3R_436()) { jj_scanpos = xsp; break; }
     }
-    return false;
-  }
-
-  private boolean jj_3R_298()
- {
-    if (jj_scan_token(BANG)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_252()
- {
-    if (jj_3R_299()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_297()
- {
-    if (jj_scan_token(TILDE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_112()
- {
-    if (jj_3R_101()) return true;
-    Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_173()) jj_scanpos = xsp;
+    if (jj_3R_437()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_250()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_297()) {
-    jj_scanpos = xsp;
-    if (jj_3R_298()) return true;
-    }
-    if (jj_3R_170()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_395()
+  private boolean jj_3R_408()
  {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_112()) return true;
+    if (jj_3R_114()) return true;
     return false;
   }
 
-  private boolean jj_3R_73()
+  private boolean jj_3R_203()
  {
-    if (jj_3R_117()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_251()) {
+    jj_scanpos = xsp;
+    if (jj_3R_252()) {
+    jj_scanpos = xsp;
+    if (jj_3R_253()) {
+    jj_scanpos = xsp;
+    if (jj_3R_254()) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_325()
+ {
+    if (jj_3R_348()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_75()
+ {
+    if (jj_3R_119()) return true;
     return false;
   }
 
   private boolean jj_3_8()
  {
-    if (jj_3R_75()) return true;
-    if (jj_3R_74()) return true;
+    if (jj_3R_77()) return true;
+    if (jj_3R_76()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_76()) { jj_scanpos = xsp; break; }
+      if (jj_3R_78()) { jj_scanpos = xsp; break; }
     }
     xsp = jj_scanpos;
     if (jj_scan_token(99)) {
@@ -9026,31 +9348,18 @@
     return false;
   }
 
-  private boolean jj_3R_202()
+  private boolean jj_3R_296()
  {
+    if (jj_scan_token(TRY)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_250()) {
+    if (jj_3R_325()) jj_scanpos = xsp;
+    if (jj_3R_123()) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_422()) {
     jj_scanpos = xsp;
-    if (jj_3R_251()) {
-    jj_scanpos = xsp;
-    if (jj_3R_252()) return true;
+    if (jj_3R_423()) return true;
     }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_428()
- {
-    if (jj_scan_token(FINALLY)) return true;
-    if (jj_3R_121()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_413()
- {
-    if (jj_scan_token(FINALLY)) return true;
-    if (jj_3R_121()) return true;
     return false;
   }
 
@@ -9058,42 +9367,25 @@
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_73()) jj_scanpos = xsp;
-    if (jj_3R_74()) return true;
+    if (jj_3R_75()) jj_scanpos = xsp;
+    if (jj_3R_76()) return true;
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3_47()
+  private boolean jj_3R_359()
  {
-    if (jj_scan_token(SEMICOLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_354()
- {
-    if (jj_3R_75()) return true;
-    if (jj_3R_112()) return true;
+    if (jj_3R_77()) return true;
+    if (jj_3R_114()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_395()) { jj_scanpos = xsp; break; }
+      if (jj_3R_408()) { jj_scanpos = xsp; break; }
     }
     if (jj_scan_token(SEMICOLON)) return true;
     return false;
   }
 
-  private boolean jj_3R_344()
- {
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_368()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3_47()) jj_scanpos = xsp;
-    if (jj_scan_token(RPAREN)) return true;
-    return false;
-  }
-
   private boolean jj_3_6()
  {
     if (jj_scan_token(AT)) return true;
@@ -9107,282 +9399,66 @@
     return false;
   }
 
-  private boolean jj_3R_334()
+  private boolean jj_3R_338()
  {
-    if (jj_3R_355()) return true;
+    if (jj_3R_360()) return true;
     return false;
   }
 
-  private boolean jj_3R_433()
+  private boolean jj_3R_337()
  {
-    if (jj_scan_token(BIT_OR)) return true;
-    if (jj_3R_249()) return true;
+    if (jj_3R_359()) return true;
     return false;
   }
 
-  private boolean jj_3R_333()
+  private boolean jj_3R_336()
  {
-    if (jj_3R_354()) return true;
+    if (jj_3R_358()) return true;
     return false;
   }
 
-  private boolean jj_3R_257()
+  private boolean jj_3R_335()
  {
-    if (jj_scan_token(DECR)) return true;
-    if (jj_3R_170()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_332()
- {
-    if (jj_3R_353()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_427()
- {
-    if (jj_scan_token(CATCH)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_3R_85()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_433()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_3R_101()) return true;
-    if (jj_scan_token(RPAREN)) return true;
-    if (jj_3R_121()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_331()
- {
-    if (jj_3R_352()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_330()
- {
-    if (jj_3R_351()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_329()
- {
-    if (jj_3R_194()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_110()
- {
-    if (jj_scan_token(INCR)) return true;
-    if (jj_3R_170()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_303()
- {
-    if (jj_3R_108()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_329()) {
-    jj_scanpos = xsp;
-    if (jj_3R_330()) {
-    jj_scanpos = xsp;
-    if (jj_3R_331()) {
-    jj_scanpos = xsp;
-    if (jj_3R_332()) {
-    jj_scanpos = xsp;
-    if (jj_3R_333()) {
-    jj_scanpos = xsp;
-    if (jj_3R_334()) return true;
-    }
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_210()
- {
-    if (jj_3R_202()) return true;
-    return false;
-  }
-
-  private boolean jj_3_9()
- {
-    if (jj_3R_77()) return true;
+    if (jj_3R_357()) return true;
     return false;
   }
 
   private boolean jj_3R_259()
  {
-    if (jj_scan_token(MINUS)) return true;
+    if (jj_scan_token(DECR)) return true;
+    if (jj_3R_171()) return true;
     return false;
   }
 
-  private boolean jj_3R_258()
+  private boolean jj_3R_324()
  {
-    if (jj_scan_token(PLUS)) return true;
+    if (jj_3R_92()) return true;
     return false;
   }
 
-  private boolean jj_3R_213()
+  private boolean jj_3R_334()
  {
-    if (jj_3R_263()) return true;
+    if (jj_3R_356()) return true;
     return false;
   }
 
-  private boolean jj_3R_412()
+  private boolean jj_3R_333()
  {
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_427()) { jj_scanpos = xsp; break; }
-    }
-    xsp = jj_scanpos;
-    if (jj_3R_428()) jj_scanpos = xsp;
+    if (jj_3R_195()) return true;
     return false;
   }
 
-  private boolean jj_3R_209()
+  private boolean jj_3R_295()
  {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_258()) {
-    jj_scanpos = xsp;
-    if (jj_3R_259()) return true;
-    }
-    if (jj_3R_170()) return true;
+    if (jj_scan_token(SYNCHRONIZED)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_123()) return true;
     return false;
   }
 
-  private boolean jj_3R_208()
- {
-    if (jj_3R_257()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_207()
- {
-    if (jj_3R_110()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_256()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3_9()) {
-    jj_scanpos = xsp;
-    if (jj_3R_303()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_322()
- {
-    if (jj_3R_344()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_293()
- {
-    if (jj_scan_token(TRY)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_322()) jj_scanpos = xsp;
-    if (jj_3R_121()) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_412()) {
-    jj_scanpos = xsp;
-    if (jj_3R_413()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_168()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_206()) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(98)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_206()
- {
-    if (jj_3R_256()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_170()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_207()) {
-    jj_scanpos = xsp;
-    if (jj_3R_208()) {
-    jj_scanpos = xsp;
-    if (jj_3R_209()) {
-    jj_scanpos = xsp;
-    if (jj_3R_210()) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_423()
- {
-    if (jj_scan_token(REM)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_105()
- {
-    if (jj_scan_token(LBRACE)) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_168()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_scan_token(RBRACE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_422()
- {
-    if (jj_scan_token(SLASH)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_421()
- {
-    if (jj_scan_token(STAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_405()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_421()) {
-    jj_scanpos = xsp;
-    if (jj_3R_422()) {
-    jj_scanpos = xsp;
-    if (jj_3R_423()) return true;
-    }
-    }
-    if (jj_3R_170()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_321()
+  private boolean jj_3R_323()
  {
     if (jj_3R_90()) return true;
     return false;
@@ -9390,203 +9466,438 @@
 
   private boolean jj_3R_307()
  {
-    if (jj_scan_token(BIT_AND)) return true;
-    if (jj_3R_306()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_382()
- {
-    if (jj_3R_170()) return true;
+    if (jj_3R_110()) return true;
     Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_405()) { jj_scanpos = xsp; break; }
+    xsp = jj_scanpos;
+    if (jj_3R_333()) {
+    jj_scanpos = xsp;
+    if (jj_3R_334()) {
+    jj_scanpos = xsp;
+    if (jj_3R_335()) {
+    jj_scanpos = xsp;
+    if (jj_3R_336()) {
+    jj_scanpos = xsp;
+    if (jj_3R_337()) {
+    jj_scanpos = xsp;
+    if (jj_3R_338()) return true;
+    }
+    }
+    }
+    }
     }
     return false;
   }
 
-  private boolean jj_3R_263()
+  private boolean jj_3R_112()
  {
-    if (jj_scan_token(EXTENDS)) return true;
-    if (jj_3R_306()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_307()) { jj_scanpos = xsp; break; }
-    }
+    if (jj_scan_token(INCR)) return true;
+    if (jj_3R_171()) return true;
     return false;
   }
 
-  private boolean jj_3R_292()
+  private boolean jj_3R_211()
  {
-    if (jj_scan_token(SYNCHRONIZED)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    if (jj_3R_90()) return true;
-    if (jj_scan_token(RPAREN)) return true;
-    if (jj_3R_121()) return true;
+    if (jj_3R_203()) return true;
     return false;
   }
 
-  private boolean jj_3R_320()
+  private boolean jj_3_9()
  {
-    if (jj_3R_88()) return true;
+    if (jj_3R_79()) return true;
     return false;
   }
 
-  private boolean jj_3R_407()
+  private boolean jj_3R_214()
+ {
+    if (jj_3R_265()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_261()
  {
     if (jj_scan_token(MINUS)) return true;
     return false;
   }
 
-  private boolean jj_3R_406()
+  private boolean jj_3R_260()
  {
     if (jj_scan_token(PLUS)) return true;
     return false;
   }
 
-  private boolean jj_3R_399()
+  private boolean jj_3R_294()
+ {
+    if (jj_scan_token(THROW)) return true;
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(SEMICOLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_210()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_406()) {
+    if (jj_3R_260()) {
     jj_scanpos = xsp;
-    if (jj_3R_407()) return true;
+    if (jj_3R_261()) return true;
     }
-    if (jj_3R_382()) return true;
+    if (jj_3R_171()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_322()
+ {
+    if (jj_3R_92()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_209()
+ {
+    if (jj_3R_259()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_258()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_9()) {
+    jj_scanpos = xsp;
+    if (jj_3R_307()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_208()
+ {
+    if (jj_3R_112()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_450()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_92()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_293()
+ {
+    if (jj_scan_token(RETURN)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_324()) jj_scanpos = xsp;
+    if (jj_scan_token(SEMICOLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_169()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_207()) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(98)) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_207()
+ {
+    if (jj_3R_258()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_171()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_208()) {
+    jj_scanpos = xsp;
+    if (jj_3R_209()) {
+    jj_scanpos = xsp;
+    if (jj_3R_210()) {
+    jj_scanpos = xsp;
+    if (jj_3R_211()) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_107()
+ {
+    if (jj_scan_token(LBRACE)) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_169()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(RBRACE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_440()
+ {
+    if (jj_scan_token(REM)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_439()
+ {
+    if (jj_scan_token(SLASH)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_292()
+ {
+    if (jj_scan_token(CONTINUE)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_323()) jj_scanpos = xsp;
+    if (jj_scan_token(SEMICOLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_438()
+ {
+    if (jj_scan_token(STAR)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_424()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_438()) {
+    jj_scanpos = xsp;
+    if (jj_3R_439()) {
+    jj_scanpos = xsp;
+    if (jj_3R_440()) return true;
+    }
+    }
+    if (jj_3R_171()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_311()
+ {
+    if (jj_scan_token(BIT_AND)) return true;
+    if (jj_3R_310()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_435()
+ {
+    if (jj_3R_442()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_265()
+ {
+    if (jj_scan_token(EXTENDS)) return true;
+    if (jj_3R_310()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_311()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_291()
+ {
+    if (jj_scan_token(BREAK)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_322()) jj_scanpos = xsp;
+    if (jj_scan_token(SEMICOLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_395()
+ {
+    if (jj_3R_171()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_424()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_426()
+ {
+    if (jj_scan_token(MINUS)) return true;
     return false;
   }
 
   private boolean jj_3_4()
  {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_72()) return true;
+    if (jj_3R_74()) return true;
     return false;
   }
 
-  private boolean jj_3R_177()
+  private boolean jj_3R_425()
  {
-    if (jj_3R_88()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_213()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_291()
- {
-    if (jj_scan_token(THROW)) return true;
-    if (jj_3R_90()) return true;
-    if (jj_scan_token(SEMICOLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_378()
- {
-    if (jj_3R_382()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_399()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_319()
- {
-    if (jj_3R_88()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_415()
- {
-    if (jj_3R_105()) return true;
+    if (jj_scan_token(PLUS)) return true;
     return false;
   }
 
   private boolean jj_3R_178()
  {
+    if (jj_3R_90()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_214()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_412()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_425()) {
+    jj_scanpos = xsp;
+    if (jj_3R_426()) return true;
+    }
+    if (jj_3R_395()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_442()
+ {
+    if (jj_3R_388()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_421()
+ {
+    if (jj_scan_token(ELSE)) return true;
+    if (jj_3R_196()) return true;
+    return false;
+  }
+
+  private boolean jj_3_46()
+ {
+    if (jj_3R_110()) return true;
+    if (jj_3R_77()) return true;
+    if (jj_3R_76()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_391()
+ {
+    if (jj_3R_395()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_412()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_428()
+ {
+    if (jj_3R_107()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_179()
+ {
     if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_86()) return true;
-    if (jj_3R_177()) return true;
+    if (jj_3R_88()) return true;
+    if (jj_3R_178()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_388()
+ {
+    if (jj_3R_92()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_450()) { jj_scanpos = xsp; break; }
+    }
     return false;
   }
 
   private boolean jj_3_27()
  {
-    if (jj_3R_93()) return true;
+    if (jj_3R_95()) return true;
     return false;
   }
 
   private boolean jj_3_26()
  {
-    if (jj_3R_92()) return true;
+    if (jj_3R_94()) return true;
     return false;
   }
 
-  private boolean jj_3R_440()
+  private boolean jj_3R_385()
  {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_90()) return true;
+    if (jj_3R_388()) return true;
     return false;
   }
 
-  private boolean jj_3R_290()
+  private boolean jj_3R_119()
  {
-    if (jj_scan_token(RETURN)) return true;
+    if (jj_scan_token(LT)) return true;
+    if (jj_3R_88()) return true;
+    if (jj_3R_178()) return true;
     Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_321()) jj_scanpos = xsp;
-    if (jj_scan_token(SEMICOLON)) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_179()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(GT)) return true;
     return false;
   }
 
-  private boolean jj_3R_91()
+  private boolean jj_3R_93()
  {
     if (jj_scan_token(LSHIFT)) return true;
     return false;
   }
 
+  private boolean jj_3R_434()
+ {
+    if (jj_3R_92()) return true;
+    return false;
+  }
+
   private boolean jj_3_25()
  {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_91()) {
+    if (jj_3R_93()) {
     jj_scanpos = xsp;
     if (jj_3_26()) {
     jj_scanpos = xsp;
     if (jj_3_27()) return true;
     }
     }
-    if (jj_3R_378()) return true;
+    if (jj_3R_391()) return true;
     return false;
   }
 
-  private boolean jj_3R_117()
+  private boolean jj_3R_384()
  {
-    if (jj_scan_token(LT)) return true;
-    if (jj_3R_86()) return true;
-    if (jj_3R_177()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_178()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_scan_token(GT)) return true;
+    if (jj_3R_111()) return true;
     return false;
   }
 
-  private boolean jj_3R_379()
+  private boolean jj_3R_392()
  {
     if (jj_scan_token(INSTANCEOF)) return true;
-    if (jj_3R_249()) return true;
+    if (jj_3R_250()) return true;
     return false;
   }
 
-  private boolean jj_3R_376()
+  private boolean jj_3R_389()
  {
-    if (jj_3R_378()) return true;
+    if (jj_3R_391()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
@@ -9595,203 +9906,194 @@
     return false;
   }
 
-  private boolean jj_3R_289()
- {
-    if (jj_scan_token(CONTINUE)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_320()) jj_scanpos = xsp;
-    if (jj_scan_token(SEMICOLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_387()
- {
-    if (jj_scan_token(GE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_386()
- {
-    if (jj_scan_token(LE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_426()
- {
-    if (jj_3R_432()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_385()
- {
-    if (jj_scan_token(GT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_384()
- {
-    if (jj_scan_token(LT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_414()
- {
-    if (jj_3R_183()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_383()
+  private boolean jj_3R_376()
  {
     Token xsp;
     xsp = jj_scanpos;
     if (jj_3R_384()) {
     jj_scanpos = xsp;
-    if (jj_3R_385()) {
-    jj_scanpos = xsp;
-    if (jj_3R_386()) {
-    jj_scanpos = xsp;
-    if (jj_3R_387()) return true;
+    if (jj_3R_385()) return true;
     }
-    }
-    }
-    if (jj_3R_376()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_288()
- {
-    if (jj_scan_token(BREAK)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_319()) jj_scanpos = xsp;
-    if (jj_scan_token(SEMICOLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_116()
- {
-    if (jj_3R_115()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_72()
- {
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_116()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_3R_88()) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_414()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_415()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_373()
- {
-    if (jj_3R_376()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_383()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_432()
- {
-    if (jj_3R_375()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_416()
- {
-    if (jj_3R_256()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_411()
- {
-    if (jj_scan_token(ELSE)) return true;
-    if (jj_3R_195()) return true;
     return false;
   }
 
   private boolean jj_3R_400()
  {
+    if (jj_scan_token(GE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_399()
+ {
+    if (jj_scan_token(LE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_427()
+ {
+    if (jj_3R_184()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_398()
+ {
+    if (jj_scan_token(GT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_397()
+ {
+    if (jj_scan_token(LT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_118()
+ {
+    if (jj_3R_117()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_396()
+ {
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_416()) {
+    if (jj_3R_397()) {
+    jj_scanpos = xsp;
+    if (jj_3R_398()) {
+    jj_scanpos = xsp;
+    if (jj_3R_399()) {
+    jj_scanpos = xsp;
+    if (jj_3R_400()) return true;
+    }
+    }
+    }
+    if (jj_3R_389()) return true;
+    return false;
+  }
+
+  private boolean jj_3_45()
+ {
+    if (jj_3R_111()) return true;
+    if (jj_scan_token(COLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_74()
+ {
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_118()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_3R_90()) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_427()) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_428()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_361()
+ {
+    if (jj_3R_376()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_386()
+ {
+    if (jj_3R_389()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_396()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_342()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_361()) jj_scanpos = xsp;
+    if (jj_scan_token(SEMICOLON)) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_434()) jj_scanpos = xsp;
+    if (jj_scan_token(SEMICOLON)) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_435()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_341()
+ {
+    if (jj_3R_111()) return true;
+    if (jj_scan_token(COLON)) return true;
+    if (jj_3R_92()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_429()
+ {
+    if (jj_3R_258()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_413()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_429()) {
     jj_scanpos = xsp;
     if (jj_scan_token(98)) return true;
     }
     return false;
   }
 
-  private boolean jj_3_46()
+  private boolean jj_3R_290()
  {
-    if (jj_3R_108()) return true;
-    if (jj_3R_75()) return true;
-    if (jj_3R_74()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_374()
- {
-    if (jj_scan_token(BIT_AND)) return true;
-    if (jj_3R_363()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_369()
- {
-    if (jj_3R_373()) return true;
+    if (jj_scan_token(FOR)) return true;
+    if (jj_scan_token(LPAREN)) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_379()) jj_scanpos = xsp;
+    if (jj_3R_341()) {
+    jj_scanpos = xsp;
+    if (jj_3R_342()) return true;
+    }
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_196()) return true;
     return false;
   }
 
-  private boolean jj_3R_390()
+  private boolean jj_3R_403()
  {
     if (jj_scan_token(SEMICOLON)) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_400()) { jj_scanpos = xsp; break; }
+      if (jj_3R_413()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_375()
+  private boolean jj_3R_387()
  {
-    if (jj_3R_90()) return true;
+    if (jj_scan_token(BIT_AND)) return true;
+    if (jj_3R_368()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_378()
+ {
+    if (jj_3R_386()) return true;
     Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_440()) { jj_scanpos = xsp; break; }
-    }
+    xsp = jj_scanpos;
+    if (jj_3R_392()) jj_scanpos = xsp;
     return false;
   }
 
-  private boolean jj_3R_372()
+  private boolean jj_3R_402()
  {
-    if (jj_3R_375()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_425()
- {
-    if (jj_3R_90()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_389()
- {
-    if (jj_3R_72()) return true;
+    if (jj_3R_74()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
@@ -9800,205 +10102,197 @@
     return false;
   }
 
-  private boolean jj_3R_371()
+  private boolean jj_3R_401()
  {
-    if (jj_3R_109()) return true;
+    if (jj_3R_309()) return true;
     return false;
   }
 
-  private boolean jj_3R_388()
- {
-    if (jj_3R_305()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_381()
+  private boolean jj_3R_394()
  {
     if (jj_scan_token(NE)) return true;
     return false;
   }
 
-  private boolean jj_3R_380()
+  private boolean jj_3R_393()
  {
     if (jj_scan_token(EQ)) return true;
     return false;
   }
 
-  private boolean jj_3R_377()
+  private boolean jj_3R_356()
  {
+    if (jj_scan_token(ENUM)) return true;
+    if (jj_3R_90()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_380()) {
-    jj_scanpos = xsp;
-    if (jj_3R_381()) return true;
-    }
-    if (jj_3R_369()) return true;
+    if (jj_3R_401()) jj_scanpos = xsp;
+    if (jj_scan_token(LBRACE)) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_402()) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(99)) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_403()) jj_scanpos = xsp;
+    if (jj_scan_token(RBRACE)) return true;
     return false;
   }
 
-  private boolean jj_3R_370()
+  private boolean jj_3R_289()
+ {
+    if (jj_scan_token(DO)) return true;
+    if (jj_3R_196()) return true;
+    if (jj_scan_token(WHILE)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_scan_token(SEMICOLON)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_390()
+ {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_393()) {
+    jj_scanpos = xsp;
+    if (jj_3R_394()) return true;
+    }
+    if (jj_3R_378()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_383()
  {
     if (jj_scan_token(XOR)) return true;
-    if (jj_3R_347()) return true;
+    if (jj_3R_351()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_373()
+ {
+    if (jj_scan_token(BIT_OR)) return true;
+    if (jj_3R_327()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_368()
+ {
+    if (jj_3R_378()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_390()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_288()
+ {
+    if (jj_scan_token(WHILE)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_196()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_419()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_310()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_353()
+ {
+    if (jj_scan_token(SC_AND)) return true;
+    if (jj_3R_299()) return true;
     return false;
   }
 
   private boolean jj_3R_351()
  {
-    if (jj_scan_token(ENUM)) return true;
-    if (jj_3R_88()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_388()) jj_scanpos = xsp;
-    if (jj_scan_token(LBRACE)) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_389()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(99)) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_390()) jj_scanpos = xsp;
-    if (jj_scan_token(RBRACE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_367()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_371()) {
-    jj_scanpos = xsp;
-    if (jj_3R_372()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_364()
- {
-    if (jj_scan_token(BIT_OR)) return true;
-    if (jj_3R_324()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_363()
- {
-    if (jj_3R_369()) return true;
+    if (jj_3R_368()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_377()) { jj_scanpos = xsp; break; }
+      if (jj_3R_387()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3_45()
- {
-    if (jj_3R_109()) return true;
-    if (jj_scan_token(COLON)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_348()
- {
-    if (jj_scan_token(SC_AND)) return true;
-    if (jj_3R_296()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_409()
- {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_306()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_347()
- {
-    if (jj_3R_363()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_374()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_356()
- {
-    if (jj_3R_367()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_305()
+  private boolean jj_3R_309()
  {
     if (jj_scan_token(IMPLEMENTS)) return true;
-    if (jj_3R_306()) return true;
+    if (jj_3R_310()) return true;
     Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_409()) { jj_scanpos = xsp; break; }
+      if (jj_3R_419()) { jj_scanpos = xsp; break; }
     }
     return false;
   }
 
-  private boolean jj_3R_338()
- {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_356()) jj_scanpos = xsp;
-    if (jj_scan_token(SEMICOLON)) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_425()) jj_scanpos = xsp;
-    if (jj_scan_token(SEMICOLON)) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_426()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_325()
+  private boolean jj_3R_329()
  {
     if (jj_scan_token(SC_OR)) return true;
-    if (jj_3R_248()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_337()
- {
-    if (jj_3R_109()) return true;
-    if (jj_scan_token(COLON)) return true;
-    if (jj_3R_90()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_324()
- {
-    if (jj_3R_347()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_370()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_408()
- {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_306()) return true;
+    if (jj_3R_249()) return true;
     return false;
   }
 
   private boolean jj_3R_287()
  {
-    if (jj_scan_token(FOR)) return true;
+    if (jj_scan_token(IF)) return true;
     if (jj_scan_token(LPAREN)) return true;
+    if (jj_3R_92()) return true;
+    if (jj_scan_token(RPAREN)) return true;
+    if (jj_3R_196()) return true;
     Token xsp;
     xsp = jj_scanpos;
-    if (jj_3R_337()) {
-    jj_scanpos = xsp;
-    if (jj_3R_338()) return true;
+    if (jj_3R_421()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_418()
+ {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_310()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_382()
+ {
+    if (jj_3R_294()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_327()
+ {
+    if (jj_3R_351()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_383()) { jj_scanpos = xsp; break; }
     }
-    if (jj_scan_token(RPAREN)) return true;
-    if (jj_3R_195()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_308()
+ {
+    if (jj_scan_token(EXTENDS)) return true;
+    if (jj_3R_310()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_418()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_381()
+ {
+    if (jj_3R_123()) return true;
     return false;
   }
 
@@ -10016,7 +10310,7 @@
   private boolean jj_lookingAhead = false;
   private boolean jj_semLA;
   private int jj_gen;
-  final private int[] jj_la1 = new int[164];
+  final private int[] jj_la1 = new int[169];
   static private int[] jj_la1_0;
   static private int[] jj_la1_1;
   static private int[] jj_la1_2;
@@ -10030,19 +10324,19 @@
 	   jj_la1_init_4();
 	}
 	private static void jj_la1_init_0() {
-	   jj_la1_0 = new int[] {0x24480800,0x4080000,0x24480800,0x1,0x0,0x0,0x20400800,0x80000,0x0,0x8000000,0x0,0x0,0x0,0x0,0x4000000,0x0,0xa54ca800,0xa54ca800,0x0,0x0,0x0,0x0,0x0,0x8000000,0x0,0xa54ca800,0xa54ca800,0x80000,0x8504a000,0xa54ca800,0x0,0x0,0x0,0x9504a000,0x9504a000,0x0,0x0,0x0,0x0,0x0,0x0,0xa544a800,0x0,0xa544a800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9504a000,0x0,0x8104a000,0x8504a000,0x8504a000,0x0,0x8504a000,0x8504a000,0x8000000,0x8000000,0x8104a000,0x8504a000,0x4000000,0x0,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9504a000,0x0,0x0,0x9504a000,0x0,0x0,0x8504a000,0x0,0x0,0x0,0x4000000,0x0,0x0,0x9504a000,0x0,0x4000000,0x0,0x10000000,0x4000000,0x0,0x0,0x0,0x0,0x0,0x10000000,0x10000000,0x9504a000,0x0,0x0,0x0,0x8504a000,0x9504a000,0x0,0x95a4f000,0x0,0x95a4f000,0x0,0x9504a000,0x0,0x0,0x9504a000,0x410000,0x410000,0x2000000,0xb544a800,0x9504a000,0x9504a000,0xb544a800,0x9504a000,0x0,0x4000000,0x4000000,0x9504a000,0x0,0x20000,0x0,0x40000000,0x9504a000,0x4000000,0x0,0x9504a000,0x9504a000,0x0,0xa54ca800,0xa54ca800,0x80000,0x8504a000,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9504a000,};
+	   jj_la1_0 = new int[] {0x24480800,0x4080000,0x24480800,0x1,0x0,0x0,0x20400800,0x80000,0x0,0x8000000,0x0,0x0,0x0,0x0,0x4000000,0x0,0xa54ca800,0xa54ca800,0x0,0x0,0x0,0x0,0x0,0x8000000,0x0,0xa54ca800,0xa54ca800,0x80000,0x8504a000,0xa54ca800,0x0,0x0,0x0,0x9504a000,0x9504a000,0x0,0x0,0x0,0x0,0x0,0x0,0xa544a800,0x0,0xa544a800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9504a000,0x0,0x8104a000,0x8504a000,0x8504a000,0x0,0x8504a000,0x8504a000,0x8000000,0x8000000,0x8104a000,0x8504a000,0x4000000,0x0,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9504a000,0x0,0x0,0x9504a000,0x0,0x0,0x8504a000,0x0,0x0,0x0,0x4000000,0x0,0x0,0x9504a000,0x0,0x4000000,0x0,0x10000000,0x4000000,0x0,0x0,0x0,0x0,0x0,0x10000000,0x10000000,0x9504a000,0x0,0x0,0x0,0x8504a000,0x9504a000,0x0,0x95a4f000,0x0,0x95a4f000,0x0,0x9504a000,0x0,0x0,0x9504a000,0x410000,0x410000,0x0,0x410000,0x9504a000,0x0,0x2000000,0xb544a800,0x9504a000,0x9504a000,0xb544a800,0x9504a000,0x0,0x9504a000,0x4000000,0x9504a000,0x0,0x20000,0x0,0x40000000,0x9504a000,0x4000000,0x0,0x9504a000,0x9504a000,0x0,0xa54ca800,0xa54ca800,0x80000,0x8504a000,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9504a000,0x4080000,};
 	}
 	private static void jj_la1_init_1() {
-	   jj_la1_1 = new int[] {0x444ce290,0x80,0x444ce290,0x0,0x40000,0x0,0x444ce200,0x80,0x0,0x0,0x8,0x0,0x0,0x8,0x80000,0x0,0x644ee3c0,0x644ee3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x644ee3c0,0x644ee3c0,0x80,0x200a0140,0x644ee3c0,0x0,0x0,0x0,0x289a0d40,0x289a0d40,0x0,0x0,0x0,0x0,0x2000000,0x0,0x444ee340,0x0,0x444ee340,0x0,0x0,0x0,0x0,0x0,0x2000000,0x0,0x0,0x289a0d40,0x40000,0x20140,0xa0140,0xa0140,0x0,0xa0140,0xa0140,0x100000,0x100000,0x20140,0x200a0140,0x80000,0x0,0x80400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x289a0d40,0x0,0x0,0x289a0d40,0x0,0x0,0xa0140,0x0,0x0,0x0,0x80400,0x0,0x0,0x289a0d40,0x0,0x80400,0x0,0x8900c00,0x80000,0x0,0x0,0x0,0x800400,0x0,0x8000800,0x8000000,0x289a0d40,0x0,0x0,0x0,0xa0140,0x289a0d40,0x0,0xb9fb0d45,0x0,0xb9fb0d45,0x0,0x289a0d40,0x0,0x0,0x289a0d40,0x0,0x0,0x0,0x6cdeef40,0x289a0d40,0x289a0d40,0x6cdeef40,0x289a0d40,0x0,0x80000,0x80000,0x289a0d40,0x0,0x0,0x0,0x0,0x289a0d40,0x80000,0x0,0x289a0d40,0x289a0d40,0x0,0x444ee3c0,0x444ee3c0,0x80,0xa0140,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x289a0d40,};
+	   jj_la1_1 = new int[] {0x444ce290,0x80,0x444ce290,0x0,0x40000,0x0,0x444ce200,0x80,0x0,0x0,0x8,0x0,0x0,0x8,0x80000,0x0,0x644ee3c0,0x644ee3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x644ee3c0,0x644ee3c0,0x80,0x200a0140,0x644ee3c0,0x0,0x0,0x0,0x28ba0d40,0x28ba0d40,0x0,0x0,0x0,0x0,0x2000000,0x0,0x444ee340,0x0,0x444ee340,0x0,0x0,0x0,0x0,0x0,0x2000000,0x0,0x0,0x289a0d40,0x40000,0x20140,0xa0140,0xa0140,0x0,0xa0140,0xa0140,0x100000,0x100000,0x20140,0x200a0140,0x80000,0x0,0x80400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x28ba0d40,0x0,0x0,0x28ba0d40,0x0,0x0,0xa0140,0x0,0x0,0x0,0x80400,0x0,0x0,0x28ba0d40,0x0,0x80400,0x0,0x8900c00,0x80000,0x0,0x0,0x0,0x800400,0x0,0x8000800,0x8000000,0x28ba0d40,0x0,0x0,0x0,0xa0140,0x28ba0d40,0x0,0xb9fb0d45,0x0,0xb9fb0d45,0x0,0x28ba0d40,0x0,0x0,0x289a0d40,0x0,0x0,0x0,0x0,0x29ba0d40,0x0,0x0,0x6cfeef40,0x28ba0d40,0x28ba0d40,0x6cfeef40,0x28ba0d40,0x0,0x28ba0d40,0x80000,0x28ba0d40,0x0,0x0,0x0,0x0,0x289a0d40,0x80000,0x0,0x28ba0d40,0x28ba0d40,0x0,0x444ee3c0,0x444ee3c0,0x80,0xa0140,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x289a0d40,0x80,};
 	}
 	private static void jj_la1_init_2() {
-	   jj_la1_2 = new int[] {0x248,0x48,0x248,0x0,0x0,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20003ff,0x0,0x420003ff,0x420003ff,0x0,0x0,0x10000000,0x40000000,0x0,0x0,0x0,0x420003ff,0x420003ff,0x0,0x20003ff,0x20003ff,0x0,0x0,0x0,0x53810fff,0x53810fff,0x0,0x0,0x0,0x0,0x0,0x40000000,0x20003ff,0x0,0x20003ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x13810fff,0x0,0x0,0x20003ff,0x20003ff,0x0,0x20003ff,0x20003ff,0x0,0x0,0x0,0x20003ff,0x20003ff,0x0,0x20003ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x13810fff,0x0,0x0,0x13810fff,0x0,0x0,0x20003ff,0x0,0x10000000,0x0,0x20003ff,0x0,0x20000000,0x13810fff,0x0,0x20003ff,0x10000000,0x11810c00,0x20003ff,0x0,0x0,0x10000000,0x0,0x0,0x1810c00,0x0,0x13810fff,0x0,0x0,0x10000000,0x20003ff,0x13810fff,0x40000000,0x53810fff,0x0,0x53810fff,0x0,0x53810fff,0x0,0x0,0x13810fff,0x0,0x0,0x0,0x13810fff,0x13810fff,0x13810fff,0x13810fff,0x13810fff,0x0,0x20003ff,0x20003ff,0x13810fff,0x10000000,0x0,0x0,0x0,0x13810fff,0x20003ff,0x0,0x53810fff,0x53810fff,0x0,0x20003ff,0x20003ff,0x0,0x20003ff,0x0,0x0,0x2,0x0,0x2,0x0,0x1b1,0x8,0x1b1,0x13810fff,};
+	   jj_la1_2 = new int[] {0x248,0x48,0x248,0x0,0x0,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20003ff,0x0,0x420003ff,0x420003ff,0x0,0x0,0x10000000,0x40000000,0x0,0x0,0x0,0x420003ff,0x420003ff,0x0,0x20003ff,0x20003ff,0x0,0x0,0x0,0x53810fff,0x53810fff,0x0,0x0,0x0,0x0,0x0,0x40000000,0x20003ff,0x0,0x20003ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x13810fff,0x0,0x0,0x20003ff,0x20003ff,0x0,0x20003ff,0x20003ff,0x0,0x0,0x0,0x20003ff,0x20003ff,0x0,0x20003ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x13810fff,0x0,0x0,0x13810fff,0x0,0x0,0x20003ff,0x0,0x10000000,0x0,0x20003ff,0x0,0x20000000,0x13810fff,0x0,0x20003ff,0x10000000,0x11810c00,0x20003ff,0x0,0x0,0x10000000,0x0,0x0,0x1810c00,0x0,0x13810fff,0x0,0x0,0x10000000,0x20003ff,0x13810fff,0x40000000,0x53810fff,0x0,0x53810fff,0x0,0x53810fff,0x0,0x0,0x13810fff,0x0,0x0,0x0,0x0,0x53810fff,0x0,0x0,0x13810fff,0x13810fff,0x13810fff,0x13810fff,0x13810fff,0x0,0x13810fff,0x20003ff,0x13810fff,0x10000000,0x0,0x0,0x0,0x13810fff,0x20003ff,0x0,0x53810fff,0x53810fff,0x0,0x20003ff,0x20003ff,0x0,0x20003ff,0x0,0x0,0x2,0x0,0x2,0x0,0x1b1,0x8,0x1b1,0x13810fff,0x0,};
 	}
 	private static void jj_la1_init_3() {
-	   jj_la1_3 = new int[] {0x24,0x24,0x24,0x0,0x0,0x10,0x20,0x0,0x80,0x0,0x0,0x8,0x8,0x0,0x20,0x8,0xa4,0xa4,0x4,0x20,0x0,0x0,0x8,0x0,0x1000000,0xa4,0xa4,0x0,0xa0,0xa0,0x8,0x40,0x21,0x3c0320,0x3c0320,0x8,0x80,0x21,0x8,0x0,0x4,0x20,0x8,0x20,0x8,0x8,0x20,0x80,0x8,0x0,0x80,0x80,0xa0,0x0,0x0,0x0,0x20,0x8,0x420,0x400,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0xe0000040,0xe0000040,0x400,0x10000,0x20000,0x2000000,0x4000000,0x1000000,0x9000,0x9000,0x0,0x6080,0x6080,0x10000000,0x300000,0x300000,0x8c00000,0x8c00000,0x300000,0x3c0320,0x300,0x300,0x20,0xc0000,0x1000000,0x0,0x80,0x0,0x80,0x0,0x10,0x0,0x3c0320,0x80,0x0,0x0,0x0,0x0,0x10,0x80,0x0,0x0,0x11,0x0,0x0,0x3c0320,0x8,0x80,0x21,0xa0,0x3c0320,0x0,0xc0024,0x800,0xc0024,0x8,0x3c0320,0xe00c0040,0xe00c0040,0x80020,0x0,0x0,0x0,0x3c0320,0x3c0320,0x3c0320,0x3c0324,0x3c0320,0x8,0x0,0x0,0x3c0320,0x0,0x0,0x2000000,0x0,0x20,0x0,0x8,0x3c0320,0x3c0320,0x8,0x24,0x24,0x0,0x20,0x0,0x8,0x0,0x8,0x0,0x8,0x0,0x0,0x0,0xa0,};
+	   jj_la1_3 = new int[] {0x24,0x24,0x24,0x0,0x0,0x10,0x20,0x0,0x80,0x0,0x0,0x8,0x8,0x0,0x20,0x8,0xa4,0xa4,0x4,0x20,0x0,0x0,0x8,0x0,0x1000000,0xa4,0xa4,0x0,0xa0,0xa0,0x8,0x40,0x21,0x3c0320,0x3c0320,0x8,0x80,0x21,0x8,0x0,0x4,0x20,0x8,0x20,0x8,0x8,0x20,0x80,0x8,0x0,0x80,0x80,0xa0,0x0,0x0,0x0,0x20,0x8,0x420,0x400,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0xe0000040,0xe0000040,0x400,0x10000,0x20000,0x2000000,0x4000000,0x1000000,0x9000,0x9000,0x0,0x6080,0x6080,0x10000000,0x300000,0x300000,0x8c00000,0x8c00000,0x300000,0x3c0320,0x300,0x300,0x20,0xc0000,0x1000000,0x0,0x80,0x0,0x80,0x0,0x10,0x0,0x3c0320,0x80,0x0,0x0,0x0,0x0,0x10,0x80,0x0,0x0,0x11,0x0,0x0,0x3c0320,0x8,0x80,0x21,0x0,0x3c0320,0x0,0xc0024,0x800,0xc0024,0x8,0x3c0320,0xe00c0040,0xe00c0040,0x80020,0x0,0x0,0x8,0x0,0x3c0320,0x800,0x0,0x3c0320,0x3c0320,0x3c0320,0x3c0324,0x3c0320,0x8,0x3c0320,0x0,0x3c0320,0x0,0x0,0x2000000,0x0,0x20,0x0,0x8,0x3c0320,0x3c0320,0x8,0x24,0x24,0x0,0x20,0x0,0x8,0x0,0x8,0x0,0x8,0x0,0x0,0x0,0xa0,0x20,};
 	}
 	private static void jj_la1_init_4() {
-	   jj_la1_4 = new int[] {0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x6ff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2000,0x2000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
+	   jj_la1_4 = new int[] {0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x6ff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2000,0x2000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
 	}
   final private JJCalls[] jj_2_rtns = new JJCalls[58];
   private boolean jj_rescan = false;
@@ -10055,7 +10349,7 @@
 	 token = new Token();
 	 jj_ntk = -1;
 	 jj_gen = 0;
-	 for (int i = 0; i < 164; i++) jj_la1[i] = -1;
+	 for (int i = 0; i < 169; i++) jj_la1[i] = -1;
 	 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
 
@@ -10082,7 +10376,7 @@
 	 token = new Token();
 	 jj_ntk = -1;
 	 jj_gen = 0;
-	 for (int i = 0; i < 164; i++) jj_la1[i] = -1;
+	 for (int i = 0; i < 169; i++) jj_la1[i] = -1;
 	 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
 
@@ -10092,7 +10386,7 @@
 	 token = new Token();
 	 jj_ntk = -1;
 	 jj_gen = 0;
-	 for (int i = 0; i < 164; i++) jj_la1[i] = -1;
+	 for (int i = 0; i < 169; i++) jj_la1[i] = -1;
 	 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
 
@@ -10102,7 +10396,7 @@
 	 token = new Token();
 	 jj_ntk = -1;
 	 jj_gen = 0;
-	 for (int i = 0; i < 164; i++) jj_la1[i] = -1;
+	 for (int i = 0; i < 169; i++) jj_la1[i] = -1;
 	 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
 
@@ -10233,7 +10527,7 @@
 	   la1tokens[jj_kind] = true;
 	   jj_kind = -1;
 	 }
-	 for (int i = 0; i < 164; i++) {
+	 for (int i = 0; i < 169; i++) {
 	   if (jj_la1[i] == jj_gen) {
 		 for (int j = 0; j < 32; j++) {
 		   if ((jj_la1_0[i] & (1<<j)) != 0) {
diff --git a/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParserTokenManager.java b/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParserTokenManager.java
index 93f3408..2a4d2a6 100644
--- a/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParserTokenManager.java
+++ b/javaparser-core/generated-sources/javacc/com/github/javaparser/GeneratedJavaParserTokenManager.java
@@ -31,7 +31,6 @@
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
 import com.github.javaparser.utils.*;
-import javax.annotation.Generated;
 import static com.github.javaparser.JavaToken.INVALID;
 import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
 import static com.github.javaparser.utils.Utils.*;
@@ -41,6 +40,7 @@
 import static com.github.javaparser.Position.*;
 import static com.github.javaparser.ast.type.ArrayType.*;
 import static com.github.javaparser.GeneratedJavaParserTokenManagerBase.*;
+import static com.github.javaparser.ast.stmt.SwitchEntry.Type.*;
 
 /** Token Manager. */
 public class GeneratedJavaParserTokenManager implements GeneratedJavaParserConstants {
@@ -114,17 +114,17 @@
       case 0:
          if ((active1 & 0x1000000000L) != 0L || (active2 & 0x100L) != 0L)
             return 2;
+         if ((active0 & 0x80L) != 0L || (active1 & 0x80000000000000L) != 0L || (active2 & 0x1L) != 0L)
+            return 56;
          if ((active0 & 0xfffffffffffff800L) != 0L || (active1 & 0x3ffL) != 0L)
          {
             jjmatchedKind = 89;
-            return 144;
+            return 141;
          }
-         if ((active0 & 0x80L) != 0L || (active1 & 0x80000000000000L) != 0L || (active2 & 0x1L) != 0L)
-            return 56;
          return -1;
       case 1:
          if ((active0 & 0x80L) != 0L)
-            return 61;
+            return 58;
          if ((active0 & 0xfffffffbfe7ff800L) != 0L || (active1 & 0x3fdL) != 0L)
          {
             if (jjmatchedPos != 1)
@@ -132,14 +132,14 @@
                jjmatchedKind = 89;
                jjmatchedPos = 1;
             }
-            return 144;
+            return 141;
          }
          if ((active0 & 0x401800000L) != 0L || (active1 & 0x2L) != 0L)
-            return 144;
+            return 141;
          return -1;
       case 2:
          if ((active0 & 0x100004c100000000L) != 0L)
-            return 144;
+            return 141;
          if ((active0 & 0xeffffb3aff7ff800L) != 0L || (active1 & 0x3fdL) != 0L)
          {
             if (jjmatchedPos != 2)
@@ -147,12 +147,12 @@
                jjmatchedKind = 89;
                jjmatchedPos = 2;
             }
-            return 144;
+            return 141;
          }
          return -1;
       case 3:
          if ((active0 & 0x2880090206058000L) != 0L || (active1 & 0x3cL) != 0L)
-            return 144;
+            return 141;
          if ((active0 & 0xc77ff2b8f97a7800L) != 0L || (active1 & 0x3c1L) != 0L)
          {
             if (jjmatchedPos != 3)
@@ -160,7 +160,7 @@
                jjmatchedKind = 89;
                jjmatchedPos = 3;
             }
-            return 144;
+            return 141;
          }
          return -1;
       case 4:
@@ -171,29 +171,29 @@
                jjmatchedKind = 89;
                jjmatchedPos = 4;
             }
-            return 144;
+            return 141;
          }
          if ((active0 & 0x83120000f01a4000L) != 0L || (active1 & 0x10L) != 0L)
-            return 144;
+            return 141;
          return -1;
       case 5:
          if ((active0 & 0x225821001001000L) != 0L || (active1 & 0x40L) != 0L)
-            return 144;
+            return 141;
          if ((active0 & 0x444870a848602800L) != 0L || (active1 & 0x381L) != 0L)
          {
             jjmatchedKind = 89;
             jjmatchedPos = 5;
-            return 144;
+            return 141;
          }
          return -1;
       case 6:
          if ((active0 & 0x300048402000L) != 0L || (active1 & 0x80L) != 0L)
-            return 144;
+            return 141;
          if ((active0 & 0x444840a800200800L) != 0L || (active1 & 0x301L) != 0L)
          {
             jjmatchedKind = 89;
             jjmatchedPos = 6;
-            return 144;
+            return 141;
          }
          return -1;
       case 7:
@@ -201,29 +201,29 @@
          {
             jjmatchedKind = 89;
             jjmatchedPos = 7;
-            return 144;
+            return 141;
          }
          if ((active0 & 0x4008000000200800L) != 0L || (active1 & 0x101L) != 0L)
-            return 144;
+            return 141;
          return -1;
       case 8:
          if ((active0 & 0x400408000000000L) != 0L)
-            return 144;
+            return 141;
          if ((active0 & 0x40002800000000L) != 0L || (active1 & 0x200L) != 0L)
          {
             jjmatchedKind = 89;
             jjmatchedPos = 8;
-            return 144;
+            return 141;
          }
          return -1;
       case 9:
          if ((active0 & 0x2800000000L) != 0L || (active1 & 0x200L) != 0L)
-            return 144;
+            return 141;
          if ((active0 & 0x40000000000000L) != 0L)
          {
             jjmatchedKind = 89;
             jjmatchedPos = 9;
-            return 144;
+            return 141;
          }
          return -1;
       case 10:
@@ -231,7 +231,7 @@
          {
             jjmatchedKind = 89;
             jjmatchedPos = 10;
-            return 144;
+            return 141;
          }
          return -1;
       default :
@@ -381,7 +381,7 @@
          break;
       case 42:
          if ((active0 & 0x80L) != 0L)
-            return jjStartNfaWithStates_0(1, 7, 61);
+            return jjStartNfaWithStates_0(1, 7, 58);
          break;
       case 43:
          if ((active1 & 0x4000000000000L) != 0L)
@@ -447,7 +447,7 @@
          return jjMoveStringLiteralDfa2_0(active0, 0x1040000400000L, active1, 0x1L, active2, 0L);
       case 102:
          if ((active0 & 0x400000000L) != 0L)
-            return jjStartNfaWithStates_0(1, 34, 144);
+            return jjStartNfaWithStates_0(1, 34, 141);
          break;
       case 104:
          return jjMoveStringLiteralDfa2_0(active0, 0x8382000000040000L, active1, 0L, active2, 0L);
@@ -466,7 +466,7 @@
             jjmatchedPos = 1;
          }
          else if ((active1 & 0x2L) != 0L)
-            return jjStartNfaWithStates_0(1, 65, 144);
+            return jjStartNfaWithStates_0(1, 65, 141);
          return jjMoveStringLiteralDfa2_0(active0, 0x6000010301302000L, active1, 0x40L, active2, 0L);
       case 112:
          return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x18L, active2, 0L);
@@ -546,7 +546,7 @@
          return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x1L, active2, 0L);
       case 114:
          if ((active0 & 0x100000000L) != 0L)
-            return jjStartNfaWithStates_0(2, 32, 144);
+            return jjStartNfaWithStates_0(2, 32, 141);
          return jjMoveStringLiteralDfa3_0(active0, 0x308000000000000L, active1, 0L, active2, 0L);
       case 115:
          return jjMoveStringLiteralDfa3_0(active0, 0x2002011800L, active1, 0L, active2, 0L);
@@ -561,11 +561,11 @@
          return jjMoveStringLiteralDfa3_0(active0, 0x800000005000000L, active1, 0L, active2, 0L);
       case 119:
          if ((active0 & 0x40000000000L) != 0L)
-            return jjStartNfaWithStates_0(2, 42, 144);
+            return jjStartNfaWithStates_0(2, 42, 141);
          break;
       case 121:
          if ((active0 & 0x1000000000000000L) != 0L)
-            return jjStartNfaWithStates_0(2, 60, 144);
+            return jjStartNfaWithStates_0(2, 60, 141);
          break;
       default :
          break;
@@ -594,25 +594,25 @@
          return jjMoveStringLiteralDfa4_0(active0, 0x40000000020000L, active1, 0L, active2, 0L);
       case 100:
          if ((active0 & 0x2000000000000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 61, 144);
+            return jjStartNfaWithStates_0(3, 61, 141);
          break;
       case 101:
          if ((active0 & 0x8000L) != 0L)
-            return jjStartNfaWithStates_0(3, 15, 144);
+            return jjStartNfaWithStates_0(3, 15, 141);
          else if ((active0 & 0x10000L) != 0L)
-            return jjStartNfaWithStates_0(3, 16, 144);
+            return jjStartNfaWithStates_0(3, 16, 141);
          else if ((active0 & 0x2000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 25, 144);
+            return jjStartNfaWithStates_0(3, 25, 141);
          else if ((active0 & 0x800000000000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 59, 144);
+            return jjStartNfaWithStates_0(3, 59, 141);
          return jjMoveStringLiteralDfa4_0(active0, 0x10008008001000L, active1, 0L, active2, 0L);
       case 103:
          if ((active0 & 0x10000000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 40, 144);
+            return jjStartNfaWithStates_0(3, 40, 141);
          break;
       case 104:
          if ((active1 & 0x4L) != 0L)
-            return jjStartNfaWithStates_0(3, 66, 144);
+            return jjStartNfaWithStates_0(3, 66, 141);
          break;
       case 105:
          return jjMoveStringLiteralDfa4_0(active0, 0x8020000000000L, active1, 0L, active2, 0L);
@@ -620,11 +620,11 @@
          return jjMoveStringLiteralDfa4_0(active0, 0x100000000000L, active1, 0L, active2, 0L);
       case 108:
          if ((active0 & 0x80000000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 43, 144);
+            return jjStartNfaWithStates_0(3, 43, 141);
          return jjMoveStringLiteralDfa4_0(active0, 0x8000800800002000L, active1, 0L, active2, 0L);
       case 109:
          if ((active0 & 0x4000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 26, 144);
+            return jjStartNfaWithStates_0(3, 26, 141);
          break;
       case 110:
          if ((active1 & 0x8L) != 0L)
@@ -635,17 +635,17 @@
          return jjMoveStringLiteralDfa4_0(active0, 0x400000000000000L, active1, 0x210L, active2, 0L);
       case 111:
          if ((active0 & 0x200000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 33, 144);
+            return jjStartNfaWithStates_0(3, 33, 141);
          return jjMoveStringLiteralDfa4_0(active0, 0x300001000000000L, active1, 0x80L, active2, 0L);
       case 114:
          if ((active0 & 0x40000L) != 0L)
-            return jjStartNfaWithStates_0(3, 18, 144);
+            return jjStartNfaWithStates_0(3, 18, 141);
          return jjMoveStringLiteralDfa4_0(active0, 0x2000000000000L, active1, 0L, active2, 0L);
       case 115:
          if ((active0 & 0x80000000000000L) != 0L)
-            return jjStartNfaWithStates_0(3, 55, 144);
+            return jjStartNfaWithStates_0(3, 55, 141);
          else if ((active1 & 0x20L) != 0L)
-            return jjStartNfaWithStates_0(3, 69, 144);
+            return jjStartNfaWithStates_0(3, 69, 141);
          return jjMoveStringLiteralDfa4_0(active0, 0x10180000L, active1, 0L, active2, 0L);
       case 116:
          return jjMoveStringLiteralDfa4_0(active0, 0x24402000200800L, active1, 0L, active2, 0L);
@@ -674,19 +674,19 @@
          return jjMoveStringLiteralDfa5_0(active0, 0x28000000000000L, active1, 0L);
       case 101:
          if ((active0 & 0x10000000L) != 0L)
-            return jjStartNfaWithStates_0(4, 28, 144);
+            return jjStartNfaWithStates_0(4, 28, 141);
          else if ((active0 & 0x8000000000000000L) != 0L)
-            return jjStartNfaWithStates_0(4, 63, 144);
+            return jjStartNfaWithStates_0(4, 63, 141);
          return jjMoveStringLiteralDfa5_0(active0, 0x400800002000L, active1, 0L);
       case 104:
          if ((active0 & 0x20000L) != 0L)
-            return jjStartNfaWithStates_0(4, 17, 144);
+            return jjStartNfaWithStates_0(4, 17, 141);
          return jjMoveStringLiteralDfa5_0(active0, 0x40000000000000L, active1, 0L);
       case 105:
          return jjMoveStringLiteralDfa5_0(active0, 0x4800000200000L, active1, 0x101L);
       case 107:
          if ((active0 & 0x4000L) != 0L)
-            return jjStartNfaWithStates_0(4, 14, 144);
+            return jjStartNfaWithStates_0(4, 14, 141);
          break;
       case 108:
          if ((active0 & 0x20000000L) != 0L)
@@ -699,21 +699,21 @@
          return jjMoveStringLiteralDfa5_0(active0, 0x8000000L, active1, 0L);
       case 114:
          if ((active0 & 0x10000000000000L) != 0L)
-            return jjStartNfaWithStates_0(4, 52, 144);
+            return jjStartNfaWithStates_0(4, 52, 141);
          return jjMoveStringLiteralDfa5_0(active0, 0x1009000001800L, active1, 0x80L);
       case 115:
          if ((active0 & 0x80000L) != 0L)
-            return jjStartNfaWithStates_0(4, 19, 144);
+            return jjStartNfaWithStates_0(4, 19, 141);
          else if ((active1 & 0x10L) != 0L)
-            return jjStartNfaWithStates_0(4, 68, 144);
+            return jjStartNfaWithStates_0(4, 68, 141);
          return jjMoveStringLiteralDfa5_0(active0, 0x400000000000000L, active1, 0x200L);
       case 116:
          if ((active0 & 0x100000L) != 0L)
-            return jjStartNfaWithStates_0(4, 20, 144);
+            return jjStartNfaWithStates_0(4, 20, 141);
          else if ((active0 & 0x80000000L) != 0L)
-            return jjStartNfaWithStates_0(4, 31, 144);
+            return jjStartNfaWithStates_0(4, 31, 141);
          else if ((active0 & 0x2000000000000L) != 0L)
-            return jjStartNfaWithStates_0(4, 49, 144);
+            return jjStartNfaWithStates_0(4, 49, 141);
          return jjMoveStringLiteralDfa5_0(active0, 0x4000000000000000L, active1, 0L);
       case 117:
          return jjMoveStringLiteralDfa5_0(active0, 0x400000L, active1, 0L);
@@ -745,19 +745,19 @@
          return jjMoveStringLiteralDfa6_0(active0, 0x2800L, active1, 0L);
       case 99:
          if ((active0 & 0x800000000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 47, 144);
+            return jjStartNfaWithStates_0(5, 47, 141);
          else if ((active0 & 0x4000000000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 50, 144);
+            return jjStartNfaWithStates_0(5, 50, 141);
          return jjMoveStringLiteralDfa6_0(active0, 0x400000000000L, active1, 0L);
       case 100:
          return jjMoveStringLiteralDfa6_0(active0, 0x8000000L, active1, 0x100L);
       case 101:
          if ((active0 & 0x1000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 24, 144);
+            return jjStartNfaWithStates_0(5, 24, 141);
          else if ((active0 & 0x20000000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 41, 144);
+            return jjStartNfaWithStates_0(5, 41, 141);
          else if ((active1 & 0x40L) != 0L)
-            return jjStartNfaWithStates_0(5, 70, 144);
+            return jjStartNfaWithStates_0(5, 70, 141);
          break;
       case 102:
          return jjMoveStringLiteralDfa6_0(active0, 0x8000000000L, active1, 0L);
@@ -765,7 +765,7 @@
          return jjMoveStringLiteralDfa6_0(active0, 0x100000000000L, active1, 0L);
       case 104:
          if ((active0 & 0x20000000000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 53, 144);
+            return jjStartNfaWithStates_0(5, 53, 141);
          break;
       case 105:
          return jjMoveStringLiteralDfa6_0(active0, 0x4400000000000000L, active1, 0x200L);
@@ -775,19 +775,19 @@
          return jjMoveStringLiteralDfa6_0(active0, 0x800000000L, active1, 0L);
       case 110:
          if ((active0 & 0x1000000000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 48, 144);
+            return jjStartNfaWithStates_0(5, 48, 141);
          return jjMoveStringLiteralDfa6_0(active0, 0x2000200000L, active1, 0L);
       case 114:
          return jjMoveStringLiteralDfa6_0(active0, 0x40000000000000L, active1, 0x1L);
       case 115:
          if ((active0 & 0x200000000000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 57, 144);
+            return jjStartNfaWithStates_0(5, 57, 141);
          break;
       case 116:
          if ((active0 & 0x1000L) != 0L)
-            return jjStartNfaWithStates_0(5, 12, 144);
+            return jjStartNfaWithStates_0(5, 12, 141);
          else if ((active0 & 0x1000000000L) != 0L)
-            return jjStartNfaWithStates_0(5, 36, 144);
+            return jjStartNfaWithStates_0(5, 36, 141);
          return jjMoveStringLiteralDfa6_0(active0, 0x8200000000000L, active1, 0x80L);
       default :
          break;
@@ -810,9 +810,9 @@
          return jjMoveStringLiteralDfa7_0(active0, 0x2000000800L, active1, 0L);
       case 101:
          if ((active0 & 0x100000000000L) != 0L)
-            return jjStartNfaWithStates_0(6, 44, 144);
+            return jjStartNfaWithStates_0(6, 44, 141);
          else if ((active0 & 0x200000000000L) != 0L)
-            return jjStartNfaWithStates_0(6, 45, 144);
+            return jjStartNfaWithStates_0(6, 45, 141);
          return jjMoveStringLiteralDfa7_0(active0, 0x400000800000000L, active1, 0x101L);
       case 102:
          return jjMoveStringLiteralDfa7_0(active0, 0x8000000000000L, active1, 0L);
@@ -820,25 +820,25 @@
          return jjMoveStringLiteralDfa7_0(active0, 0x4000000000000000L, active1, 0L);
       case 110:
          if ((active0 & 0x2000L) != 0L)
-            return jjStartNfaWithStates_0(6, 13, 144);
+            return jjStartNfaWithStates_0(6, 13, 141);
          break;
       case 111:
          return jjMoveStringLiteralDfa7_0(active0, 0x40000000000000L, active1, 0L);
       case 115:
          if ((active0 & 0x8000000L) != 0L)
-            return jjStartNfaWithStates_0(6, 27, 144);
+            return jjStartNfaWithStates_0(6, 27, 141);
          else if ((active1 & 0x80L) != 0L)
-            return jjStartNfaWithStates_0(6, 71, 144);
+            return jjStartNfaWithStates_0(6, 71, 141);
          break;
       case 116:
          if ((active0 & 0x400000L) != 0L)
-            return jjStartNfaWithStates_0(6, 22, 144);
+            return jjStartNfaWithStates_0(6, 22, 141);
          return jjMoveStringLiteralDfa7_0(active0, 0x400000000000L, active1, 0x200L);
       case 117:
          return jjMoveStringLiteralDfa7_0(active0, 0x200000L, active1, 0L);
       case 121:
          if ((active0 & 0x40000000L) != 0L)
-            return jjStartNfaWithStates_0(6, 30, 144);
+            return jjStartNfaWithStates_0(6, 30, 141);
          break;
       default :
          break;
@@ -859,9 +859,9 @@
          return jjMoveStringLiteralDfa8_0(active0, 0x8000000000L, active1, 0L);
       case 101:
          if ((active0 & 0x200000L) != 0L)
-            return jjStartNfaWithStates_0(7, 21, 144);
+            return jjStartNfaWithStates_0(7, 21, 141);
          else if ((active0 & 0x4000000000000000L) != 0L)
-            return jjStartNfaWithStates_0(7, 62, 144);
+            return jjStartNfaWithStates_0(7, 62, 141);
          return jjMoveStringLiteralDfa8_0(active0, 0x402000000000L, active1, 0L);
       case 105:
          return jjMoveStringLiteralDfa8_0(active0, 0L, active1, 0x200L);
@@ -869,17 +869,17 @@
          return jjMoveStringLiteralDfa8_0(active0, 0x440000800000000L, active1, 0L);
       case 112:
          if ((active0 & 0x8000000000000L) != 0L)
-            return jjStartNfaWithStates_0(7, 51, 144);
+            return jjStartNfaWithStates_0(7, 51, 141);
          break;
       case 115:
          if ((active1 & 0x1L) != 0L)
-            return jjStartNfaWithStates_0(7, 64, 144);
+            return jjStartNfaWithStates_0(7, 64, 141);
          else if ((active1 & 0x100L) != 0L)
-            return jjStartNfaWithStates_0(7, 72, 144);
+            return jjStartNfaWithStates_0(7, 72, 141);
          break;
       case 116:
          if ((active0 & 0x800L) != 0L)
-            return jjStartNfaWithStates_0(7, 11, 144);
+            return jjStartNfaWithStates_0(7, 11, 141);
          break;
       default :
          break;
@@ -898,11 +898,11 @@
    {
       case 100:
          if ((active0 & 0x400000000000L) != 0L)
-            return jjStartNfaWithStates_0(8, 46, 144);
+            return jjStartNfaWithStates_0(8, 46, 141);
          break;
       case 101:
          if ((active0 & 0x8000000000L) != 0L)
-            return jjStartNfaWithStates_0(8, 39, 144);
+            return jjStartNfaWithStates_0(8, 39, 141);
          break;
       case 105:
          return jjMoveStringLiteralDfa9_0(active0, 0x40000000000000L, active1, 0L);
@@ -910,7 +910,7 @@
          return jjMoveStringLiteralDfa9_0(active0, 0x2000000000L, active1, 0L);
       case 116:
          if ((active0 & 0x400000000000000L) != 0L)
-            return jjStartNfaWithStates_0(8, 58, 144);
+            return jjStartNfaWithStates_0(8, 58, 141);
          return jjMoveStringLiteralDfa9_0(active0, 0x800000000L, active1, 0L);
       case 118:
          return jjMoveStringLiteralDfa9_0(active0, 0L, active1, 0x200L);
@@ -931,15 +931,15 @@
    {
       case 101:
          if ((active1 & 0x200L) != 0L)
-            return jjStartNfaWithStates_0(9, 73, 144);
+            return jjStartNfaWithStates_0(9, 73, 141);
          break;
       case 102:
          if ((active0 & 0x2000000000L) != 0L)
-            return jjStartNfaWithStates_0(9, 37, 144);
+            return jjStartNfaWithStates_0(9, 37, 141);
          break;
       case 115:
          if ((active0 & 0x800000000L) != 0L)
-            return jjStartNfaWithStates_0(9, 35, 144);
+            return jjStartNfaWithStates_0(9, 35, 141);
          break;
       case 122:
          return jjMoveStringLiteralDfa10_0(active0, 0x40000000000000L, active1, 0L);
@@ -977,7 +977,7 @@
    {
       case 100:
          if ((active0 & 0x40000000000000L) != 0L)
-            return jjStartNfaWithStates_0(11, 54, 144);
+            return jjStartNfaWithStates_0(11, 54, 141);
          break;
       default :
          break;
@@ -1026,13 +1026,13 @@
    0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0x501f0003ffc3L
 };
 static final long[] jjbitVec12 = {
-   0x0L, 0x3cdf000000000000L, 0xfffffffbffffd740L, 0xffbfffffffffffffL
+   0x0L, 0xbcdf000000000000L, 0xfffffffbffffd740L, 0xffbfffffffffffffL
 };
 static final long[] jjbitVec13 = {
    0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffffc03L, 0xffffffffffffffffL
 };
 static final long[] jjbitVec14 = {
-   0xfffe00ffffffffffL, 0xfffffffe027fffffL, 0x80ffL, 0x707ffffff0000L
+   0xfffeffffffffffffL, 0xfffffffe027fffffL, 0x80ffL, 0x707ffffff0000L
 };
 static final long[] jjbitVec15 = {
    0xffffffff00000800L, 0xfffec000000007ffL, 0xffffffffffffffffL, 0x9c00c060002fffffL
@@ -1041,22 +1041,22 @@
    0xfffffffd0000L, 0xffffffffffffe000L, 0x2003fffffffffL, 0x43007fffffffc00L
 };
 static final long[] jjbitVec17 = {
-   0x110043fffffL, 0x1ffffffL, 0x1ffd00000000L, 0x0L
+   0x110043fffffL, 0x7ff01ffffffL, 0x3fdfffff00000000L, 0x0L
 };
 static final long[] jjbitVec18 = {
-   0x23fffffffffffff0L, 0xfefe0003ff010000L, 0x23c5fdfffff99fe0L, 0x80f0003b0004000L
+   0x23fffffffffffff0L, 0xfffe0003ff010000L, 0x23c5fdfffff99fe1L, 0x180f0003b0004000L
 };
 static final long[] jjbitVec19 = {
-   0x36dfdfffff987e0L, 0x1c00005e000000L, 0x23edfdfffffbbfe0L, 0x2000300010000L
+   0x36dfdfffff987e0L, 0x1c00005e000000L, 0x23edfdfffffbbfe0L, 0x202000300010000L
 };
 static final long[] jjbitVec20 = {
    0x23edfdfffff99fe0L, 0x20003b0000000L, 0x3ffc718d63dc7e8L, 0x200000000010000L
 };
 static final long[] jjbitVec21 = {
-   0x23effdfffffddfe0L, 0x303000000L, 0x23effdfffffddfe0L, 0x6000340000000L
+   0x23fffdfffffddfe0L, 0x307000000L, 0x23effdfffffddfe1L, 0x6000340000000L
 };
 static final long[] jjbitVec22 = {
-   0x27fffffffffddfe0L, 0xfc00000300004000L, 0x2ffbfffffc7fffe0L, 0x7fL
+   0x27fffffffffddfe0L, 0xfc00000380704000L, 0x2ffbfffffc7fffe0L, 0x7fL
 };
 static final long[] jjbitVec23 = {
    0x800dfffffffffffeL, 0x7fL, 0x200decaefef02596L, 0xf000005fL
@@ -1071,19 +1071,19 @@
    0xffffffffffffffffL, 0xffffffff3d7f3dffL, 0x7f3dffffffff3dffL, 0xffffffffff7fff3dL
 };
 static final long[] jjbitVec27 = {
-   0xffffffffff3dffffL, 0x7ffffffL, 0xffffffff0000ffffL, 0x1fffffffffffffL
+   0xffffffffff3dffffL, 0x7ffffffL, 0xffffffff0000ffffL, 0x3f3fffffffffffffL
 };
 static final long[] jjbitVec28 = {
-   0xffffffffffffffffL, 0xffff9fffffffffffL, 0xffffffff07fffffeL, 0x1c7ffffffffffL
+   0xffffffffffffffffL, 0xffff9fffffffffffL, 0xffffffff07fffffeL, 0x1ffc7ffffffffffL
 };
 static final long[] jjbitVec29 = {
    0x3ffff0003dfffL, 0x1dfff0003ffffL, 0xfffffffffffffL, 0x18800000L
 };
 static final long[] jjbitVec30 = {
-   0xffffffff00000000L, 0xffffffffffffffL, 0xffff05ffffffffffL, 0x3fffffffffffffL
+   0xffffffff00000000L, 0xffffffffffffffL, 0xffff05ffffffff9fL, 0x3fffffffffffffL
 };
 static final long[] jjbitVec31 = {
-   0x1fffffffL, 0x1f3fffffff0000L, 0xfffffffffffL, 0xfeL
+   0x7fffffffL, 0x1f3fffffff0000L, 0xffff0fffffffffffL, 0x3ffL
 };
 static final long[] jjbitVec32 = {
    0xffffffff007fffffL, 0x1fffffL, 0x8000000000L, 0x0L
@@ -1092,7 +1092,7 @@
    0xfffffffffffe0L, 0xfe0L, 0xfc00c001fffffff8L, 0x3fffffffffL
 };
 static final long[] jjbitVec34 = {
-   0xfffffffffL, 0x3ffffffffc00e000L, 0x0L, 0x63de0000000000L
+   0xfffffffffL, 0x3ffffffffc00e000L, 0x1ffL, 0x63de0000000000L
 };
 static final long[] jjbitVec35 = {
    0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0x0L
@@ -1101,7 +1101,7 @@
    0xffffffff3f3fffffL, 0x3fffffffaaff3f3fL, 0x5fdfffffffffffffL, 0x1fdc1fff0fcf1fdcL
 };
 static final long[] jjbitVec37 = {
-   0x8000000000000000L, 0x8002000000100001L, 0x7ffffff1fff0000L, 0x0L
+   0x8000000000000000L, 0x8002000000100001L, 0xffffffff1fff0000L, 0x0L
 };
 static final long[] jjbitVec38 = {
    0xf3ffbd503e2ffc84L, 0xffffffff000043e0L, 0x1ffL, 0x0L
@@ -1119,34 +1119,34 @@
    0x1f3e03fe000000e0L, 0xfffffffffffffffeL, 0xfffffffee07fffffL, 0xf7ffffffffffffffL
 };
 static final long[] jjbitVec43 = {
-   0xfffe3fffffffffe0L, 0xffffffffffffffffL, 0x7ffffff00007fffL, 0xffff000000000000L
+   0xfffe7fffffffffe0L, 0xffffffffffffffffL, 0x7ffffff00007fffL, 0xffff000000000000L
 };
 static final long[] jjbitVec44 = {
    0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffffffL, 0x0L
 };
 static final long[] jjbitVec45 = {
-   0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0x1fffL
+   0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0x7ffffffffffL
 };
 static final long[] jjbitVec46 = {
    0xffffffffffffffffL, 0xffffffffffffffffL, 0x1fffL, 0x3fffffffffff0000L
 };
 static final long[] jjbitVec47 = {
-   0xc00ffff1fffL, 0x80007fffffffffffL, 0xffffffff00ffffffL, 0xffffffffffffL
+   0xc00ffff1fffL, 0x80007fffffffffffL, 0xffffffff3fffffffL, 0xffffffffffffL
 };
 static final long[] jjbitVec48 = {
-   0xfffffffcff800000L, 0xffffffffffffffffL, 0x7ff000f79ffL, 0xff00000000000000L
+   0xfffffffcff800000L, 0xffffffffffffffffL, 0xff7ffffffff9ffL, 0xff80000000000000L
 };
 static final long[] jjbitVec49 = {
-   0x1000007fffff7bbL, 0xfffffffffffffL, 0xffffffffffffcL, 0x8fc000000000000L
+   0x1000007fffff7bbL, 0xfffffffffffffL, 0xffffffffffffcL, 0x28fc000000000000L
 };
 static final long[] jjbitVec50 = {
-   0xffff003ffffffc00L, 0x1fffffff0000007fL, 0x7fffffffffff0L, 0x8000L
+   0xffff003ffffffc00L, 0x1fffffff0000007fL, 0x7fffffffffff0L, 0x7c00ffdf00008000L
 };
 static final long[] jjbitVec51 = {
-   0x1ffffffffffL, 0x47fffff00000ff7L, 0x3e62ffffffffffffL, 0x1c07ff38000005L
+   0x1ffffffffffL, 0xc47fffff00000ff7L, 0x3e62ffffffffffffL, 0x1c07ff38000005L
 };
 static final long[] jjbitVec52 = {
-   0x7f7f007e7e7eL, 0x0L, 0x0L, 0x7ffffffffL
+   0xffff7f7f007e7e7eL, 0xffff003ff7ffffffL, 0xffffffffffffffffL, 0x7ffffffffL
 };
 static final long[] jjbitVec53 = {
    0xffffffffffffffffL, 0xffffffffffffffffL, 0xffff000fffffffffL, 0xffffffffffff87fL
@@ -1170,37 +1170,37 @@
    0x0L, 0x0L, 0x420243cffffffffL, 0xff7fffffff7fffffL
 };
 static final long[] jjbitVec60 = {
-   0xffffffffffffffffL, 0x3cdfffffffffffffL, 0xfffffffbffffd740L, 0xffbfffffffffffffL
+   0xffffffffffffffffL, 0xbcdfffffffffffffL, 0xfffffffbffffd740L, 0xffbfffffffffffffL
 };
 static final long[] jjbitVec61 = {
    0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffffcfbL, 0xffffffffffffffffL
 };
 static final long[] jjbitVec62 = {
-   0xfffe00ffffffffffL, 0xfffffffe027fffffL, 0xbffffffffffe80ffL, 0x707ffffff00b6L
+   0xfffeffffffffffffL, 0xfffffffe027fffffL, 0xbffffffffffe80ffL, 0x707ffffff00b6L
 };
 static final long[] jjbitVec63 = {
-   0xffffffff07ff081fL, 0xffffc3ffffffffffL, 0xffffffffffffffffL, 0x9ffffdffbfefffffL
+   0xffffffff17ff083fL, 0xffffc3ffffffffffL, 0xffffffffffffffffL, 0x9ffffdffbfefffffL
 };
 static final long[] jjbitVec64 = {
    0xffffffffffff8000L, 0xffffffffffffe7ffL, 0x3ffffffffffffL, 0x43fffffffffffffL
 };
 static final long[] jjbitVec65 = {
-   0x3fffffffffffL, 0xfffffffL, 0x1ffd00000000L, 0x7ffffff000000000L
+   0x3fffffffffffL, 0x7ff0fffffffL, 0x3fdfffff00000000L, 0xfffffffffff00000L
 };
 static final long[] jjbitVec66 = {
-   0xffffffffffffffffL, 0xfefeffcfffffffffL, 0xf3c5fdfffff99feeL, 0x80fffcfb080799fL
+   0xffffffffffffffffL, 0xfffeffcfffffffffL, 0xf3c5fdfffff99fefL, 0x180fffcfb080799fL
 };
 static final long[] jjbitVec67 = {
-   0xd36dfdfffff987eeL, 0x3fffc05e023987L, 0xf3edfdfffffbbfeeL, 0x2ffcf00013bbfL
+   0xd36dfdfffff987eeL, 0x3fffc05e023987L, 0xf3edfdfffffbbfeeL, 0xfe02ffcf00013bbfL
 };
 static final long[] jjbitVec68 = {
    0xf3edfdfffff99feeL, 0x2ffcfb0c0399fL, 0xc3ffc718d63dc7ecL, 0x200ffc000813dc7L
 };
 static final long[] jjbitVec69 = {
-   0xe3effdfffffddfeeL, 0xffcf03603ddfL, 0xf3effdfffffddfecL, 0x6ffcf40603ddfL
+   0xe3fffdfffffddfefL, 0xffcf07603ddfL, 0xf3effdfffffddfefL, 0x6ffcf40603ddfL
 };
 static final long[] jjbitVec70 = {
-   0xe7fffffffffddfecL, 0xfc00ffcf00807ddfL, 0x2ffbfffffc7fffecL, 0xc0000ff5f847fL
+   0xfffffffffffddfefL, 0xfc00ffcf80f07ddfL, 0x2ffbfffffc7fffecL, 0xcffc0ff5f847fL
 };
 static final long[] jjbitVec71 = {
    0x87fffffffffffffeL, 0x3ff7fffL, 0x3bffecaefef02596L, 0xf3ff3f5fL
@@ -1212,31 +1212,31 @@
    0xffffffffffffffffL, 0xffffffffffff03ffL, 0xffffffff3fffffffL, 0xf7ffffffffff20bfL
 };
 static final long[] jjbitVec74 = {
-   0xffffffffff3dffffL, 0xe7ffffffL, 0xffffffff0000ffffL, 0x1fffffffffffffL
+   0xffffffffff3dffffL, 0xe7ffffffL, 0xffffffff0000ffffL, 0x3f3fffffffffffffL
 };
 static final long[] jjbitVec75 = {
    0x1fffff001fdfffL, 0xddfff000fffffL, 0xffffffffffffffffL, 0x3ff388fffffL
 };
 static final long[] jjbitVec76 = {
-   0xffffffff03ff3800L, 0xffffffffffffffL, 0xffff07ffffffffffL, 0x3fffffffffffffL
+   0xffffffff03ff7800L, 0xffffffffffffffL, 0xffff07ffffffffffL, 0x3fffffffffffffL
 };
 static final long[] jjbitVec77 = {
-   0xfff0fff1fffffffL, 0x1f3fffffffffc0L, 0xffff0fffffffffffL, 0x3ff03ffL
+   0xfff0fff7fffffffL, 0x1f3fffffffffc0L, 0xffff0fffffffffffL, 0x3ff03ffL
 };
 static final long[] jjbitVec78 = {
-   0xffffffff0fffffffL, 0x9fffffff7fffffffL, 0x8003ff03ffL, 0x0L
+   0xffffffff0fffffffL, 0x9fffffff7fffffffL, 0x3fff008003ff03ffL, 0x0L
 };
 static final long[] jjbitVec79 = {
    0xffffffffffffffffL, 0xff80003ff0fffL, 0xffffffffffffffffL, 0xfffffffffffffL
 };
 static final long[] jjbitVec80 = {
-   0xffffffffffffffL, 0x3fffffffffffe3ffL, 0x0L, 0x7ffffffff70000L
+   0xffffffffffffffL, 0x3fffffffffffe3ffL, 0x1ffL, 0x3fffffffff70000L
 };
 static final long[] jjbitVec81 = {
-   0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xf000007fffffffffL
+   0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfbffffffffffffffL
 };
 static final long[] jjbitVec82 = {
-   0x80007c000000f800L, 0x8002fc1f00100001L, 0x7ffffff1fff0000L, 0x1ffe21fff0000L
+   0x80007c000000f800L, 0x8002ffdf00100001L, 0xffffffff1fff0000L, 0x1ffe21fff0000L
 };
 static final long[] jjbitVec83 = {
    0xffff7fffffffffffL, 0xffffffff7fffffffL, 0xffffffffffffffffL, 0xff81fffffffffL
@@ -1248,25 +1248,25 @@
    0x1f3efffe000000e0L, 0xfffffffffffffffeL, 0xfffffffee67fffffL, 0xf7ffffffffffffffL
 };
 static final long[] jjbitVec86 = {
-   0xfffffff1fffL, 0xbff0ffffffffffffL, 0xffffffff80ffffffL, 0x3ffffffffffffL
+   0xfffffff1fffL, 0xbff0ffffffffffffL, 0xffffffffffffffffL, 0x3ffffffffffffL
 };
 static final long[] jjbitVec87 = {
-   0x10000ffffffffffL, 0xfffffffffffffL, 0xffffffffffffffffL, 0x8ffffff03ff001fL
+   0x10000ffffffffffL, 0xfffffffffffffL, 0xffffffffffffffffL, 0x28ffffff03ff003fL
 };
 static final long[] jjbitVec88 = {
-   0xffff3fffffffffffL, 0x1fffffff000fffffL, 0xffffffffffffffffL, 0x3ff8001L
+   0xffff3fffffffffffL, 0x1fffffff000fffffL, 0xffffffffffffffffL, 0x7fffffff03ff8001L
 };
 static final long[] jjbitVec89 = {
-   0x7fffffffffffffL, 0xc7fffff03ff3fffL, 0xffffffffffffffffL, 0x7cffff38000007L
+   0x7fffffffffffffL, 0xfc7fffff03ff3fffL, 0xffffffffffffffffL, 0x7cffff38000007L
 };
 static final long[] jjbitVec90 = {
-   0x7f7f007e7e7eL, 0x0L, 0x0L, 0x3ff37ffffffffffL
+   0xffff7f7f007e7e7eL, 0xffff003ff7ffffffL, 0xffffffffffffffffL, 0x3ff37ffffffffffL
 };
 static final long[] jjbitVec91 = {
    0x5f7ffdffe0f8007fL, 0xffffffffffffffdbL, 0x3ffffffffffffL, 0xfffffffffff80000L
 };
 static final long[] jjbitVec92 = {
-   0x18007f0000ffffL, 0xffdf02000000e000L, 0xffffffffffffffffL, 0x9fffffffffffffffL
+   0x18ffff0000ffffL, 0xffdf02000000e000L, 0xffffffffffffffffL, 0x9fffffffffffffffL
 };
 static final long[] jjbitVec93 = {
    0x87fffffe03ff0010L, 0xffffffc007fffffeL, 0x7fffffffffffffffL, 0xe0000631cfcfcfcL
@@ -1274,7 +1274,7 @@
 private int jjMoveNfa_0(int startState, int curPos)
 {
    int startsAt = 0;
-   jjnewStateCnt = 144;
+   jjnewStateCnt = 141;
    int i = 1;
    jjstateSet[0] = startState;
    int kind = 0x7fffffff;
@@ -1289,7 +1289,7 @@
          {
             switch(jjstateSet[--i])
             {
-               case 144:
+               case 141:
                case 43:
                   if ((0x3ff00100fffc1ffL & l) == 0L)
                      break;
@@ -1297,22 +1297,12 @@
                      kind = 89;
                   { jjCheckNAddTwoStates(43, 49); }
                   break;
-               case 56:
-                  if (curChar == 42)
-                     jjstateSet[jjnewStateCnt++] = 61;
-                  else if (curChar == 47)
-                  {
-                     if (kind > 5)
-                        kind = 5;
-                     { jjCheckNAddStates(0, 2); }
-                  }
-                  break;
                case 0:
                   if ((0x3ff000000000000L & l) != 0L)
                   {
                      if (kind > 75)
                         kind = 75;
-                     { jjCheckNAddStates(3, 17); }
+                     { jjCheckNAddStates(0, 14); }
                   }
                   else if ((0x100001200L & l) != 0L)
                   {
@@ -1320,7 +1310,7 @@
                         kind = 1;
                   }
                   else if (curChar == 47)
-                     { jjAddStates(18, 19); }
+                     { jjAddStates(15, 16); }
                   else if (curChar == 36)
                   {
                      if (kind > 89)
@@ -1328,13 +1318,23 @@
                      { jjCheckNAddTwoStates(43, 49); }
                   }
                   else if (curChar == 34)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   else if (curChar == 39)
-                     { jjAddStates(24, 26); }
+                     { jjAddStates(21, 23); }
                   else if (curChar == 46)
                      jjstateSet[jjnewStateCnt++] = 2;
                   if (curChar == 48)
-                     { jjAddStates(27, 34); }
+                     { jjAddStates(24, 31); }
+                  break;
+               case 56:
+                  if (curChar == 42)
+                     jjstateSet[jjnewStateCnt++] = 58;
+                  else if (curChar == 47)
+                  {
+                     if (kind > 5)
+                        kind = 5;
+                     { jjCheckNAdd(57); }
+                  }
                   break;
                case 1:
                   if (curChar == 46)
@@ -1345,7 +1345,7 @@
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(35, 38); }
+                  { jjCheckNAddStates(32, 35); }
                   break;
                case 3:
                   if ((0x3ff000000000000L & l) != 0L)
@@ -1367,7 +1367,7 @@
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(39, 41); }
+                  { jjCheckNAddStates(36, 38); }
                   break;
                case 8:
                   if ((0x3ff000000000000L & l) != 0L)
@@ -1385,11 +1385,11 @@
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(42, 45); }
+                  { jjCheckNAddStates(39, 42); }
                   break;
                case 12:
                   if (curChar == 39)
-                     { jjAddStates(24, 26); }
+                     { jjAddStates(21, 23); }
                   break;
                case 13:
                   if ((0xffffff7fffffdbffL & l) != 0L)
@@ -1437,15 +1437,15 @@
                   break;
                case 27:
                   if (curChar == 34)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 28:
                   if ((0xfffffffbffffdbffL & l) != 0L)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 30:
                   if ((0x8400000000L & l) != 0L)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 32:
                   if ((0x3ff000000000000L & l) != 0L)
@@ -1461,7 +1461,7 @@
                   break;
                case 35:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 37:
                   if (curChar == 34 && kind > 88)
@@ -1469,11 +1469,11 @@
                   break;
                case 38:
                   if ((0xff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(46, 50); }
+                     { jjCheckNAddStates(43, 47); }
                   break;
                case 39:
                   if ((0xff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 40:
                   if ((0xf000000000000L & l) != 0L)
@@ -1520,79 +1520,79 @@
                   break;
                case 55:
                   if (curChar == 47)
-                     { jjAddStates(18, 19); }
+                     { jjAddStates(15, 16); }
                   break;
                case 57:
                   if ((0xffffffffffffdbffL & l) == 0L)
                      break;
                   if (kind > 5)
                      kind = 5;
-                  { jjCheckNAddStates(0, 2); }
+                  { jjCheckNAdd(57); }
                   break;
                case 58:
-                  if ((0x2400L & l) != 0L && kind > 5)
-                     kind = 5;
-                  break;
-               case 59:
-                  if (curChar == 10 && kind > 5)
-                     kind = 5;
-                  break;
-               case 60:
-                  if (curChar == 13)
+                  if (curChar == 42)
                      jjstateSet[jjnewStateCnt++] = 59;
                   break;
-               case 61:
-                  if (curChar == 42)
-                     jjstateSet[jjnewStateCnt++] = 62;
-                  break;
-               case 62:
+               case 59:
                   if ((0xffff7fffffffffffL & l) != 0L && kind > 6)
                      kind = 6;
                   break;
-               case 63:
+               case 60:
                   if (curChar == 42)
-                     jjstateSet[jjnewStateCnt++] = 61;
+                     jjstateSet[jjnewStateCnt++] = 58;
                   break;
-               case 64:
+               case 61:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 75)
                      kind = 75;
-                  { jjCheckNAddStates(3, 17); }
+                  { jjCheckNAddStates(0, 14); }
+                  break;
+               case 62:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(62, 63); }
+                  break;
+               case 63:
+               case 99:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAdd(64); }
                   break;
                case 65:
                   if ((0x3ff000000000000L & l) != 0L)
                      { jjCheckNAddTwoStates(65, 66); }
                   break;
                case 66:
-               case 102:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAdd(67); }
-                  break;
-               case 68:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(68, 69); }
-                  break;
-               case 69:
-               case 113:
+               case 110:
                   if ((0x3ff000000000000L & l) != 0L && kind > 75)
                      kind = 75;
                   break;
-               case 70:
+               case 67:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(70, 71); }
+                     { jjCheckNAddTwoStates(67, 68); }
+                  break;
+               case 68:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(69, 10); }
+                  break;
+               case 70:
+                  if ((0x280000000000L & l) != 0L)
+                     { jjCheckNAdd(71); }
                   break;
                case 71:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(72, 10); }
+                     { jjCheckNAddStates(48, 50); }
+                  break;
+               case 72:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(72, 73); }
                   break;
                case 73:
-                  if ((0x280000000000L & l) != 0L)
-                     { jjCheckNAdd(74); }
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(71, 10); }
                   break;
                case 74:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(51, 53); }
+                     { jjCheckNAddStates(51, 54); }
                   break;
                case 75:
                   if ((0x3ff000000000000L & l) != 0L)
@@ -1600,269 +1600,257 @@
                   break;
                case 76:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(74, 10); }
-                  break;
-               case 77:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(54, 57); }
+                     { jjCheckNAdd(77); }
                   break;
                case 78:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(78, 79); }
+                  if ((0x280000000000L & l) != 0L)
+                     { jjCheckNAdd(79); }
                   break;
                case 79:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 80)
+                     kind = 80;
+                  { jjCheckNAddStates(55, 57); }
+                  break;
+               case 80:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAdd(80); }
+                     { jjCheckNAddTwoStates(80, 81); }
                   break;
                case 81:
-                  if ((0x280000000000L & l) != 0L)
-                     { jjCheckNAdd(82); }
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 80)
+                     kind = 80;
+                  { jjCheckNAddTwoStates(79, 10); }
                   break;
                case 82:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(58, 60); }
+                  { jjCheckNAddStates(58, 61); }
                   break;
                case 83:
                   if ((0x3ff000000000000L & l) != 0L)
                      { jjCheckNAddTwoStates(83, 84); }
                   break;
                case 84:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 80)
-                     kind = 80;
-                  { jjCheckNAddTwoStates(82, 10); }
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAdd(85); }
                   break;
                case 85:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 80)
-                     kind = 80;
-                  { jjCheckNAddStates(61, 64); }
-                  break;
-               case 86:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(86, 87); }
-                  break;
-               case 87:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAdd(88); }
-                  break;
-               case 88:
                   if (curChar != 46)
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(65, 67); }
+                  { jjCheckNAddStates(62, 64); }
                   break;
-               case 89:
+               case 86:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(68, 71); }
+                  { jjCheckNAddStates(65, 68); }
+                  break;
+               case 87:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(87, 88); }
+                  break;
+               case 88:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 80)
+                     kind = 80;
+                  { jjCheckNAddTwoStates(89, 10); }
                   break;
                case 90:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(90, 91); }
+                  if ((0x280000000000L & l) != 0L)
+                     { jjCheckNAdd(91); }
                   break;
                case 91:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddTwoStates(92, 10); }
+                  { jjCheckNAddStates(69, 71); }
+                  break;
+               case 92:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(92, 93); }
                   break;
                case 93:
-                  if ((0x280000000000L & l) != 0L)
-                     { jjCheckNAdd(94); }
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 80)
+                     kind = 80;
+                  { jjCheckNAddTwoStates(91, 10); }
                   break;
                case 94:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(72, 74); }
+                  { jjCheckNAddStates(72, 75); }
                   break;
                case 95:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(95, 96); }
-                  break;
-               case 96:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 80)
-                     kind = 80;
-                  { jjCheckNAddTwoStates(94, 10); }
+                  if (curChar == 48)
+                     { jjAddStates(24, 31); }
                   break;
                case 97:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 80)
-                     kind = 80;
-                  { jjCheckNAddStates(75, 78); }
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddStates(76, 78); }
                   break;
                case 98:
-                  if (curChar == 48)
-                     { jjAddStates(27, 34); }
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(98, 99); }
                   break;
                case 100:
-                  if ((0x3ff000000000000L & l) != 0L)
+                  if ((0xff000000000000L & l) != 0L)
                      { jjCheckNAddStates(79, 81); }
                   break;
                case 101:
-                  if ((0x3ff000000000000L & l) != 0L)
+                  if ((0xff000000000000L & l) != 0L)
                      { jjCheckNAddTwoStates(101, 102); }
                   break;
-               case 103:
+               case 102:
                   if ((0xff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(82, 84); }
+                     { jjCheckNAdd(64); }
                   break;
                case 104:
-                  if ((0xff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(104, 105); }
+                  if ((0x3000000000000L & l) != 0L)
+                     { jjCheckNAddStates(82, 84); }
                   break;
                case 105:
-                  if ((0xff000000000000L & l) != 0L)
-                     { jjCheckNAdd(67); }
-                  break;
-               case 107:
                   if ((0x3000000000000L & l) != 0L)
-                     { jjCheckNAddStates(85, 87); }
+                     { jjCheckNAddTwoStates(105, 106); }
+                  break;
+               case 106:
+                  if ((0x3000000000000L & l) != 0L)
+                     { jjCheckNAdd(64); }
                   break;
                case 108:
-                  if ((0x3000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(108, 109); }
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 75)
+                     kind = 75;
+                  { jjCheckNAddTwoStates(109, 110); }
                   break;
                case 109:
-                  if ((0x3000000000000L & l) != 0L)
-                     { jjCheckNAdd(67); }
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(109, 110); }
                   break;
                case 111:
-                  if ((0x3ff000000000000L & l) == 0L)
+                  if ((0xff000000000000L & l) == 0L)
                      break;
                   if (kind > 75)
                      kind = 75;
                   { jjCheckNAddTwoStates(112, 113); }
                   break;
                case 112:
-                  if ((0x3ff000000000000L & l) != 0L)
+                  if ((0xff000000000000L & l) != 0L)
                      { jjCheckNAddTwoStates(112, 113); }
                   break;
-               case 114:
-                  if ((0xff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 75)
-                     kind = 75;
-                  { jjCheckNAddTwoStates(115, 116); }
-                  break;
-               case 115:
-                  if ((0xff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(115, 116); }
-                  break;
-               case 116:
+               case 113:
                   if ((0xff000000000000L & l) != 0L && kind > 75)
                      kind = 75;
                   break;
-               case 118:
+               case 115:
                   if ((0x3000000000000L & l) == 0L)
                      break;
                   if (kind > 75)
                      kind = 75;
-                  { jjCheckNAddTwoStates(119, 120); }
+                  { jjCheckNAddTwoStates(116, 117); }
                   break;
-               case 119:
+               case 116:
                   if ((0x3000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(119, 120); }
+                     { jjCheckNAddTwoStates(116, 117); }
                   break;
-               case 120:
+               case 117:
                   if ((0x3000000000000L & l) != 0L && kind > 75)
                      kind = 75;
                   break;
-               case 122:
+               case 119:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(88, 90); }
+                     { jjCheckNAddStates(85, 87); }
+                  break;
+               case 120:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(120, 121); }
+                  break;
+               case 121:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAdd(122); }
+                  break;
+               case 122:
+                  if (curChar == 46)
+                     jjstateSet[jjnewStateCnt++] = 123;
                   break;
                case 123:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(123, 124); }
+                     { jjCheckNAddStates(88, 90); }
                   break;
                case 124:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAdd(125); }
+                     { jjCheckNAddTwoStates(124, 125); }
                   break;
                case 125:
-                  if (curChar == 46)
-                     jjstateSet[jjnewStateCnt++] = 126;
-                  break;
-               case 126:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(91, 93); }
+                     { jjCheckNAdd(126); }
                   break;
                case 127:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(127, 128); }
+                  if ((0x280000000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 128;
                   break;
                case 128:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAdd(129); }
-                  break;
-               case 130:
-                  if ((0x280000000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 131;
-                  break;
-               case 131:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(94, 96); }
+                  { jjCheckNAddStates(91, 93); }
                   break;
-               case 132:
+               case 129:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(132, 133); }
+                     { jjCheckNAddTwoStates(129, 130); }
                   break;
-               case 133:
-               case 143:
+               case 130:
+               case 140:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 80)
                      kind = 80;
                   { jjCheckNAdd(10); }
                   break;
-               case 135:
+               case 132:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddStates(97, 100); }
+                     { jjCheckNAddStates(94, 97); }
                   break;
-               case 136:
+               case 133:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(136, 137); }
+                     { jjCheckNAddTwoStates(133, 134); }
+                  break;
+               case 134:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(135, 136); }
+                  break;
+               case 135:
+                  if (curChar == 46)
+                     { jjCheckNAdd(136); }
                   break;
                case 137:
-                  if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(138, 139); }
+                  if ((0x280000000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 138;
                   break;
                case 138:
-                  if (curChar == 46)
-                     { jjCheckNAdd(139); }
-                  break;
-               case 140:
-                  if ((0x280000000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 141;
-                  break;
-               case 141:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
                   if (kind > 80)
                      kind = 80;
-                  { jjCheckNAddStates(101, 103); }
+                  { jjCheckNAddStates(98, 100); }
                   break;
-               case 142:
+               case 139:
                   if ((0x3ff000000000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(142, 143); }
+                     { jjCheckNAddTwoStates(139, 140); }
                   break;
                default : break;
             }
@@ -1875,7 +1863,7 @@
          {
             switch(jjstateSet[--i])
             {
-               case 144:
+               case 141:
                   if ((0x87fffffe87fffffeL & l) != 0L)
                   {
                      if (kind > 89)
@@ -1897,15 +1885,15 @@
                   break;
                case 3:
                   if (curChar == 95)
-                     { jjAddStates(104, 105); }
+                     { jjAddStates(101, 102); }
                   break;
                case 5:
                   if ((0x2000000020L & l) != 0L)
-                     { jjAddStates(106, 107); }
+                     { jjAddStates(103, 104); }
                   break;
                case 8:
                   if (curChar == 95)
-                     { jjAddStates(108, 109); }
+                     { jjAddStates(105, 106); }
                   break;
                case 10:
                   if ((0x5000000050L & l) != 0L && kind > 80)
@@ -1917,7 +1905,7 @@
                   break;
                case 15:
                   if (curChar == 92)
-                     { jjAddStates(110, 112); }
+                     { jjAddStates(107, 109); }
                   break;
                case 16:
                   if ((0x14404410000000L & l) != 0L)
@@ -1949,15 +1937,15 @@
                   break;
                case 28:
                   if ((0xffffffffefffffffL & l) != 0L)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 29:
                   if (curChar == 92)
-                     { jjAddStates(113, 115); }
+                     { jjAddStates(110, 112); }
                   break;
                case 30:
                   if ((0x14404410000000L & l) != 0L)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 31:
                   if (curChar == 117)
@@ -1977,7 +1965,7 @@
                   break;
                case 35:
                   if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAddStates(20, 23); }
+                     { jjCheckNAddStates(17, 20); }
                   break;
                case 36:
                   if (curChar == 92)
@@ -2044,182 +2032,182 @@
                case 57:
                   if (kind > 5)
                      kind = 5;
-                  { jjAddStates(0, 2); }
+                  jjstateSet[jjnewStateCnt++] = 57;
                   break;
-               case 62:
+               case 59:
                   if (kind > 6)
                      kind = 6;
                   break;
-               case 65:
+               case 62:
                   if (curChar == 95)
-                     { jjAddStates(116, 117); }
+                     { jjAddStates(113, 114); }
                   break;
-               case 67:
+               case 64:
                   if ((0x100000001000L & l) != 0L && kind > 74)
                      kind = 74;
                   break;
-               case 68:
+               case 65:
                   if (curChar == 95)
-                     { jjAddStates(118, 119); }
+                     { jjAddStates(115, 116); }
                   break;
-               case 70:
+               case 67:
                   if (curChar == 95)
-                     { jjAddStates(120, 121); }
+                     { jjAddStates(117, 118); }
+                  break;
+               case 69:
+                  if ((0x2000000020L & l) != 0L)
+                     { jjAddStates(119, 120); }
                   break;
                case 72:
-                  if ((0x2000000020L & l) != 0L)
-                     { jjAddStates(122, 123); }
+                  if (curChar == 95)
+                     { jjAddStates(121, 122); }
                   break;
                case 75:
                   if (curChar == 95)
-                     { jjAddStates(124, 125); }
+                     { jjAddStates(123, 124); }
                   break;
-               case 78:
-                  if (curChar == 95)
-                     { jjAddStates(126, 127); }
+               case 77:
+                  if ((0x2000000020L & l) != 0L)
+                     { jjAddStates(125, 126); }
                   break;
                case 80:
-                  if ((0x2000000020L & l) != 0L)
-                     { jjAddStates(128, 129); }
+                  if (curChar == 95)
+                     { jjAddStates(127, 128); }
                   break;
                case 83:
                   if (curChar == 95)
-                     { jjAddStates(130, 131); }
+                     { jjAddStates(129, 130); }
                   break;
-               case 86:
+               case 87:
                   if (curChar == 95)
-                     { jjAddStates(132, 133); }
+                     { jjAddStates(131, 132); }
                   break;
-               case 90:
-                  if (curChar == 95)
-                     { jjAddStates(134, 135); }
+               case 89:
+                  if ((0x2000000020L & l) != 0L)
+                     { jjAddStates(133, 134); }
                   break;
                case 92:
-                  if ((0x2000000020L & l) != 0L)
-                     { jjAddStates(136, 137); }
-                  break;
-               case 95:
                   if (curChar == 95)
-                     { jjAddStates(138, 139); }
+                     { jjAddStates(135, 136); }
+                  break;
+               case 96:
+                  if ((0x100000001000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 97;
+                  break;
+               case 97:
+                  if ((0x7e0000007eL & l) != 0L)
+                     { jjCheckNAddStates(76, 78); }
+                  break;
+               case 98:
+                  if ((0x7e8000007eL & l) != 0L)
+                     { jjCheckNAddTwoStates(98, 99); }
                   break;
                case 99:
-                  if ((0x100000001000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 100;
-                  break;
-               case 100:
                   if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAddStates(79, 81); }
+                     { jjCheckNAdd(64); }
                   break;
                case 101:
-                  if ((0x7e8000007eL & l) != 0L)
-                     { jjCheckNAddTwoStates(101, 102); }
-                  break;
-               case 102:
-                  if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAdd(67); }
-                  break;
-               case 104:
                   if (curChar == 95)
-                     { jjAddStates(140, 141); }
+                     { jjAddStates(137, 138); }
                   break;
-               case 106:
+               case 103:
                   if ((0x400000004L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 107;
+                     jjstateSet[jjnewStateCnt++] = 104;
+                  break;
+               case 105:
+                  if (curChar == 95)
+                     { jjAddStates(139, 140); }
+                  break;
+               case 107:
+                  if ((0x100000001000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 108;
                   break;
                case 108:
-                  if (curChar == 95)
-                     { jjAddStates(142, 143); }
-                  break;
-               case 110:
-                  if ((0x100000001000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 111;
-                  break;
-               case 111:
                   if ((0x7e0000007eL & l) == 0L)
                      break;
                   if (kind > 75)
                      kind = 75;
-                  { jjCheckNAddTwoStates(112, 113); }
+                  { jjCheckNAddTwoStates(109, 110); }
                   break;
-               case 112:
+               case 109:
                   if ((0x7e8000007eL & l) != 0L)
-                     { jjCheckNAddTwoStates(112, 113); }
+                     { jjCheckNAddTwoStates(109, 110); }
                   break;
-               case 113:
+               case 110:
                   if ((0x7e0000007eL & l) != 0L && kind > 75)
                      kind = 75;
                   break;
-               case 115:
+               case 112:
                   if (curChar == 95)
-                     { jjAddStates(144, 145); }
+                     { jjAddStates(141, 142); }
                   break;
-               case 117:
+               case 114:
                   if ((0x400000004L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 118;
+                     jjstateSet[jjnewStateCnt++] = 115;
+                  break;
+               case 116:
+                  if (curChar == 95)
+                     { jjAddStates(143, 144); }
+                  break;
+               case 118:
+                  if ((0x100000001000000L & l) != 0L)
+                     { jjCheckNAddTwoStates(119, 122); }
                   break;
                case 119:
-                  if (curChar == 95)
-                     { jjAddStates(146, 147); }
+                  if ((0x7e0000007eL & l) != 0L)
+                     { jjCheckNAddStates(85, 87); }
+                  break;
+               case 120:
+                  if ((0x7e8000007eL & l) != 0L)
+                     { jjCheckNAddTwoStates(120, 121); }
                   break;
                case 121:
-                  if ((0x100000001000000L & l) != 0L)
-                     { jjCheckNAddTwoStates(122, 125); }
+                  if ((0x7e0000007eL & l) != 0L)
+                     { jjCheckNAdd(122); }
                   break;
-               case 122:
+               case 123:
                   if ((0x7e0000007eL & l) != 0L)
                      { jjCheckNAddStates(88, 90); }
                   break;
-               case 123:
-                  if ((0x7e8000007eL & l) != 0L)
-                     { jjCheckNAddTwoStates(123, 124); }
-                  break;
                case 124:
+                  if ((0x7e8000007eL & l) != 0L)
+                     { jjCheckNAddTwoStates(124, 125); }
+                  break;
+               case 125:
                   if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAdd(125); }
+                     { jjCheckNAdd(126); }
                   break;
                case 126:
-                  if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAddStates(91, 93); }
-                  break;
-               case 127:
-                  if ((0x7e8000007eL & l) != 0L)
-                     { jjCheckNAddTwoStates(127, 128); }
-                  break;
-               case 128:
-                  if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAdd(129); }
+                  if ((0x1000000010000L & l) != 0L)
+                     { jjAddStates(145, 146); }
                   break;
                case 129:
-                  if ((0x1000000010000L & l) != 0L)
-                     { jjAddStates(148, 149); }
+                  if (curChar == 95)
+                     { jjAddStates(147, 148); }
+                  break;
+               case 131:
+                  if ((0x100000001000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 132;
                   break;
                case 132:
-                  if (curChar == 95)
-                     { jjAddStates(150, 151); }
+                  if ((0x7e0000007eL & l) != 0L)
+                     { jjCheckNAddStates(94, 97); }
+                  break;
+               case 133:
+                  if ((0x7e8000007eL & l) != 0L)
+                     { jjCheckNAddTwoStates(133, 134); }
                   break;
                case 134:
-                  if ((0x100000001000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 135;
-                  break;
-               case 135:
                   if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAddStates(97, 100); }
+                     { jjCheckNAddTwoStates(135, 136); }
                   break;
                case 136:
-                  if ((0x7e8000007eL & l) != 0L)
-                     { jjCheckNAddTwoStates(136, 137); }
-                  break;
-               case 137:
-                  if ((0x7e0000007eL & l) != 0L)
-                     { jjCheckNAddTwoStates(138, 139); }
+                  if ((0x1000000010000L & l) != 0L)
+                     { jjAddStates(149, 150); }
                   break;
                case 139:
-                  if ((0x1000000010000L & l) != 0L)
-                     { jjAddStates(152, 153); }
-                  break;
-               case 142:
                   if (curChar == 95)
-                     { jjAddStates(154, 155); }
+                     { jjAddStates(151, 152); }
                   break;
                default : break;
             }
@@ -2236,7 +2224,7 @@
          {
             switch(jjstateSet[--i])
             {
-               case 144:
+               case 141:
                case 43:
                   if (!jjCanMove_3(hiByte, i1, i2, l1, l2))
                      break;
@@ -2263,7 +2251,7 @@
                   break;
                case 28:
                   if (jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     { jjAddStates(20, 23); }
+                     { jjAddStates(17, 20); }
                   break;
                case 42:
                   if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
@@ -2277,9 +2265,9 @@
                      break;
                   if (kind > 5)
                      kind = 5;
-                  { jjAddStates(0, 2); }
+                  jjstateSet[jjnewStateCnt++] = 57;
                   break;
-               case 62:
+               case 59:
                   if (jjCanMove_1(hiByte, i1, i2, l1, l2) && kind > 6)
                      kind = 6;
                   break;
@@ -2294,7 +2282,7 @@
          kind = 0x7fffffff;
       }
       ++curPos;
-      if ((i = jjnewStateCnt) == (startsAt = 144 - (jjnewStateCnt = startsAt)))
+      if ((i = jjnewStateCnt) == (startsAt = 141 - (jjnewStateCnt = startsAt)))
          return curPos;
       try { curChar = input_stream.readChar(); }
       catch(java.io.IOException e) { return curPos; }
@@ -2405,16 +2393,16 @@
    return t;
 }
 static final int[] jjnextStates = {
-   57, 58, 60, 65, 66, 67, 68, 69, 70, 71, 72, 10, 78, 79, 80, 86, 
-   87, 88, 56, 63, 28, 29, 36, 37, 13, 15, 26, 99, 103, 106, 110, 114, 
-   117, 121, 134, 3, 4, 5, 10, 8, 10, 11, 7, 8, 10, 11, 28, 29, 
-   39, 36, 37, 75, 10, 77, 74, 75, 10, 77, 83, 10, 85, 82, 83, 10, 
-   85, 89, 92, 10, 90, 91, 92, 10, 95, 10, 97, 94, 95, 10, 97, 101, 
-   102, 67, 104, 105, 67, 108, 109, 67, 123, 124, 125, 127, 128, 129, 132, 133, 
-   10, 136, 137, 138, 139, 142, 143, 10, 3, 4, 6, 7, 8, 9, 16, 17, 
-   19, 30, 38, 40, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 
-   81, 82, 83, 84, 86, 87, 90, 91, 93, 94, 95, 96, 104, 105, 108, 109, 
-   115, 116, 119, 120, 130, 131, 132, 133, 140, 141, 142, 143, 
+   62, 63, 64, 65, 66, 67, 68, 69, 10, 75, 76, 77, 83, 84, 85, 56, 
+   60, 28, 29, 36, 37, 13, 15, 26, 96, 100, 103, 107, 111, 114, 118, 131, 
+   3, 4, 5, 10, 8, 10, 11, 7, 8, 10, 11, 28, 29, 39, 36, 37, 
+   72, 10, 74, 71, 72, 10, 74, 80, 10, 82, 79, 80, 10, 82, 86, 89, 
+   10, 87, 88, 89, 10, 92, 10, 94, 91, 92, 10, 94, 98, 99, 64, 101, 
+   102, 64, 105, 106, 64, 120, 121, 122, 124, 125, 126, 129, 130, 10, 133, 134, 
+   135, 136, 139, 140, 10, 3, 4, 6, 7, 8, 9, 16, 17, 19, 30, 38, 
+   40, 62, 63, 65, 66, 67, 68, 70, 71, 72, 73, 75, 76, 78, 79, 80, 
+   81, 83, 84, 87, 88, 90, 91, 92, 93, 101, 102, 105, 106, 112, 113, 116, 
+   117, 127, 128, 129, 130, 137, 138, 139, 140, 
 };
 private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
 {
@@ -2904,7 +2892,7 @@
   {
     int i;
     jjround = 0x80000001;
-    for (i = 144; i-- > 0;)
+    for (i = 141; i-- > 0;)
       jjrounds[i] = 0x80000000;
   }
 
@@ -2956,8 +2944,8 @@
 };
     protected SimpleCharStream  input_stream;
 
-    private final int[] jjrounds = new int[144];
-    private final int[] jjstateSet = new int[2 * 144];
+    private final int[] jjrounds = new int[141];
+    private final int[] jjstateSet = new int[2 * 141];
     private final StringBuilder jjimage = new StringBuilder();
     private StringBuilder image = jjimage;
     private int jjimageLen;
diff --git a/javaparser-core/javaparser-core.iml b/javaparser-core/javaparser-core.iml
deleted file mode 100644
index 055eff4..0000000
--- a/javaparser-core/javaparser-core.iml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/javacc-support" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/target/generated-sources/java-templates" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/target/generated-sources/javacc" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/target/generated-sources/license" isTestSource="false" generated="true" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-core/pom.xml b/javaparser-core/pom.xml
index 356b13d..e024434 100644
--- a/javaparser-core/pom.xml
+++ b/javaparser-core/pom.xml
@@ -2,7 +2,7 @@
     <parent>
         <artifactId>javaparser-parent</artifactId>
         <groupId>com.github.javaparser</groupId>
-        <version>3.5.16-SNAPSHOT</version>
+        <version>3.14.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -47,59 +47,6 @@
                     </execution>
                 </executions>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>animal-sniffer-maven-plugin</artifactId>
-                <configuration>
-                    <signature>
-                        <!-- Make sure only the API of this JDK is used -->
-                        <groupId>org.codehaus.mojo.signature</groupId>
-                        <artifactId>java18</artifactId>
-                        <version>1.0</version>
-                    </signature>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>animal-sniffer</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>check</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-enforcer-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>enforce-versions</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>enforce</goal>
-                        </goals>
-                        <configuration>
-                            <rules>
-                                <requireJavaVersion>
-                                    <!-- Make sure a compiler of this version is used -->
-                                    <version>${java.version}</version>
-                                </requireJavaVersion>
-                                <enforceBytecodeVersion>
-                                    <!-- Make sure the dependencies are compiled for our Java version -->
-                                    <maxJdkVersion>${java.version}</maxJdkVersion>
-                                </enforceBytecodeVersion>
-                            </rules>
-                        </configuration>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>extra-enforcer-rules</artifactId>
-                        <version>1.0-beta-6</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
             <!-- Generate an OSGi-enabled MANIFEST during the build -->
             <plugin>
                 <groupId>biz.aQute.bnd</groupId>
diff --git a/javaparser-core/src/main/java/com/github/javaparser/CommentsInserter.java b/javaparser-core/src/main/java/com/github/javaparser/CommentsInserter.java
index 869883c..321b439 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/CommentsInserter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/CommentsInserter.java
@@ -22,6 +22,7 @@
 package com.github.javaparser;
 
 import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.comments.Comment;
 import com.github.javaparser.ast.comments.LineComment;
@@ -31,9 +32,9 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.TreeSet;
-import java.util.stream.Collectors;
 
 import static com.github.javaparser.ast.Node.NODE_BY_BEGIN_POSITION;
+import static java.util.stream.Collectors.*;
 
 /**
  * Assigns comments to nodes of the AST.
@@ -57,8 +58,7 @@
             return;
 
         /* I should sort all the direct children and the comments, if a comment
-         is the first thing then it
-         a comment to the CompilationUnit */
+         is the first thing then it is a comment to the CompilationUnit */
 
         // FIXME if there is no package it could be also a comment to the following class...
         // so I could use some heuristics in these cases to distinguish the two
@@ -87,15 +87,16 @@
             insertComments((CompilationUnit) node, commentsToAttribute);
         }
 
-        // the comments can:
-        // 1) Inside one of the child, then it is the child that have to
-        // associate them
-        // 2) If they are not inside a child they could be preceeding nothing, a
-        // comment or a child
-        // if they preceed a child they are assigned to it, otherweise they
-        // remain "orphans"
+        /* the comment can...
+         1) be inside one of the children, then the comment should be associated to this child
+         2) be outside all children. They could be preceding nothing, a comment or a child.
+            If they preceed a child they are assigned to it, otherwise they remain "orphans"
+         */
 
-        List<Node> children = node.getChildNodes();
+        List<Node> children = node.getChildNodes().stream()
+                // Never attribute comments to modifiers.
+                .filter(n -> !(n instanceof Modifier))
+                .collect(toList());
 
         for (Node child : children) {
             TreeSet<Comment> commentsInsideChild = new TreeSet<>(NODE_BY_BEGIN_POSITION);
@@ -103,7 +104,7 @@
                     commentsToAttribute.stream()
                             .filter(c -> c.getRange().isPresent())
                             .filter(c -> PositionUtils.nodeContains(child, c,
-                                    configuration.isDoNotConsiderAnnotationsAsNodeStartForCodeAttribution())).collect(Collectors.toList()));
+                                    configuration.isIgnoreAnnotationsWhenAttributingComments())).collect(toList()));
             commentsToAttribute.removeAll(commentsInsideChild);
             insertComments(child, commentsInsideChild);
         }
@@ -121,7 +122,7 @@
 
         childrenAndComments.addAll(commentsToAttribute);
         PositionUtils.sortByBeginPosition(childrenAndComments,
-                configuration.isDoNotConsiderAnnotationsAsNodeStartForCodeAttribution());
+                configuration.isIgnoreAnnotationsWhenAttributingComments());
 
         for (Node thing : childrenAndComments) {
             if (thing instanceof Comment) {
@@ -176,7 +177,7 @@
         if (!node.getRange().isPresent() || !lineComment.getRange().isPresent()) {
             return false;
         }
-        
+
         // The node start and end at the same line as the comment,
         // let's give to it the comment
         if (node.getBegin().get().line == lineComment.getBegin().get().line
diff --git a/javaparser-core/src/main/java/com/github/javaparser/HasParentNode.java b/javaparser-core/src/main/java/com/github/javaparser/HasParentNode.java
index 03df0d6..ae7d5ce 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/HasParentNode.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/HasParentNode.java
@@ -25,41 +25,70 @@
 import com.github.javaparser.ast.observer.Observable;
 
 import java.util.Optional;
+import java.util.function.Predicate;
 
 /**
- * An object that has a parent node.
+ * An object that can have a parent node.
  */
 public interface HasParentNode<T> extends Observable {
 
     /**
-     * Return the parent node or null, if no parent is set.
+     * Returns the parent node, or {@code Optional.empty} if no parent is set.
      */
     Optional<Node> getParentNode();
 
     /**
-     * Set the parent node.
+     * Sets the parent node.
      *
-     * @param parentNode the parent node or null, to set no parent
-     * @return return <i>this</i>
+     * @param parentNode the parent node, or {@code null} to set no parent.
+     * @return return {@code this}
      */
     T setParentNode(Node parentNode);
 
     /**
-     * <i>this</i> for everything except NodeLists. NodeLists use their parent as their children parent.
+     * Returns the parent node from the perspective of the children of this node.
+     * <p>
+     * That is, this method returns {@code this} for everything except {@code NodeList}. A {@code NodeList} returns its
+     * parent node instead. This is because a {@code NodeList} sets the parent of all its children to its own parent
+     * node (see {@link com.github.javaparser.ast.NodeList} for details).
      */
     Node getParentNodeForChildren();
 
     /**
-     * Get the ancestor of the node having the given type, or null if no ancestor of the given type is found.
+     * Walks the parents of this node and returns the first node of type {@code type}, or {@code empty()} if none is
+     * found. The given type may also be an interface type, such as one of the {@code NodeWith...} interface types.
      */
-    default <N> Optional<N> getAncestorOfType(Class<N> classType) {
-        Node parent = getParentNode().orElse(null);
-        while (parent != null) {
-            if (classType.isAssignableFrom(parent.getClass())) {
-                return Optional.of(classType.cast(parent));
+    default <N> Optional<N> findAncestor(Class<N> type) {
+        return findAncestor(type, x -> true);
+    }
+
+    /**
+     * Walks the parents of this node and returns the first node of type {@code type} that matches {@code predicate}, or
+     * {@code empty()} if none is found. The given type may also be an interface type, such as one of the
+     * {@code NodeWith...} interface types.
+     */
+    default <N> Optional<N> findAncestor(Class<N> type, Predicate<N> predicate) {
+        Optional<Node> possibleParent = getParentNode();
+        while (possibleParent.isPresent()) {
+            Node parent = possibleParent.get();
+            if (type.isAssignableFrom(parent.getClass()) && predicate.test(type.cast(parent))) {
+                return Optional.of(type.cast(parent));
             }
-            parent = parent.getParentNode().orElse(null);
+            possibleParent = parent.getParentNode();
         }
         return Optional.empty();
     }
+
+    /**
+     * Determines whether this {@code HasParentNode} node is a descendant of the given node. A node is <i>not</i> a
+     * descendant of itself.
+     *
+     * @param ancestor the node for which to determine whether it has this node as an ancestor.
+     * @return {@code true} if this node is a descendant of the given node, and {@code false} otherwise.
+     * @see Node#isAncestorOf(Node)
+     */
+    default boolean isDescendantOf(Node ancestor) {
+        return findAncestor(Node.class, n -> n == ancestor).isPresent();
+    }
+
 }
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 7b8ee87..bfc2536 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/JavaParser.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/JavaParser.java
@@ -27,13 +27,16 @@
 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.body.TypeDeclaration;
 import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.modules.ModuleDeclaration;
+import com.github.javaparser.ast.modules.ModuleDirective;
 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.javadoc.Javadoc;
+import com.github.javaparser.ast.type.TypeParameter;
 
 import java.io.*;
 import java.nio.charset.Charset;
@@ -48,16 +51,15 @@
  * Parse Java source code and creates Abstract Syntax Trees.
  *
  * @author Júlio Vilmar Gesser
+ * @see StaticJavaParser
  */
 public final class JavaParser {
     private final ParserConfiguration configuration;
 
     private GeneratedJavaParser astParser = null;
-    private static ParserConfiguration staticConfiguration = new ParserConfiguration();
 
     /**
-     * Instantiate the parser with default configuration. Note that parsing can also be done with the static methods on
-     * this class.
+     * Instantiate the parser with default configuration. Note that parsing can also be done with the static methods {@link StaticJavaParser}.
      * Creating an instance will reduce setup time between parsing files.
      */
     public JavaParser() {
@@ -65,7 +67,7 @@
     }
 
     /**
-     * Instantiate the parser. Note that parsing can also be done with the static methods on this class.
+     * Instantiate the parser. Note that parsing can also be done with the static methods {@link StaticJavaParser}.
      * Creating an instance will reduce setup time between parsing files.
      */
     public JavaParser(ParserConfiguration configuration) {
@@ -73,25 +75,7 @@
     }
 
     /**
-     * Get the configuration for the static parse... methods.
-     * This is a STATIC field, so modifying it will directly change how all static parse... methods work!
-     */
-    public static ParserConfiguration getStaticConfiguration() {
-        return staticConfiguration;
-    }
-
-    /**
-     * Set the configuration for the static parse... methods.
-     * This is a STATIC field, so modifying it will directly change how all static parse... methods work!
-     */
-    public static void setStaticConfiguration(ParserConfiguration staticConfiguration) {
-        JavaParser.staticConfiguration = staticConfiguration;
-    }
-
-    /**
-     * Get the non-static configuration for this parser.
-     *
-     * @return The non-static configuration for this parser.
+     * @return The configuration for this parser.
      */
     public ParserConfiguration getParserConfiguration() {
         return this.configuration;
@@ -121,11 +105,15 @@
     public <N extends Node> ParseResult<N> parse(ParseStart<N> start, Provider provider) {
         assertNotNull(start);
         assertNotNull(provider);
+
+        for (PreProcessor preProcessor : configuration.getPreProcessors()) {
+            provider = preProcessor.process(provider);
+        }
+
         final GeneratedJavaParser parser = getParserForProvider(provider);
         try {
             N resultNode = start.parse(parser);
-            ParseResult<N> result = new ParseResult<>(resultNode, parser.problems, parser.getTokens(),
-                    parser.getCommentsCollection());
+            ParseResult<N> result = new ParseResult<>(resultNode, parser.problems, parser.getCommentsCollection());
 
             configuration.getPostProcessors().forEach(postProcessor ->
                     postProcessor.process(result, configuration));
@@ -136,7 +124,7 @@
         } catch (Exception e) {
             final String message = e.getMessage() == null ? "Unknown error" : e.getMessage();
             parser.problems.add(new Problem(message, null, e));
-            return new ParseResult<>(null, parser.problems, parser.getTokens(), parser.getCommentsCollection());
+            return new ParseResult<>(null, parser.problems, parser.getCommentsCollection());
         } finally {
             try {
                 provider.close();
@@ -155,21 +143,20 @@
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static CompilationUnit parse(final InputStream in, Charset encoding) {
-        return simplifiedParse(COMPILATION_UNIT, provider(in, encoding));
+    public ParseResult<CompilationUnit> parse(final InputStream in, Charset encoding) {
+        return parse(COMPILATION_UNIT, provider(in, encoding));
     }
 
     /**
      * Parses the Java code contained in the {@link InputStream} and returns a
      * {@link CompilationUnit} that represents it.<br>
-     * Note: Uses UTF-8 encoding
      *
      * @param in {@link InputStream} containing Java source code. It will be closed after parsing.
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static CompilationUnit parse(final InputStream in) {
-        return parse(in, UTF8);
+    public ParseResult<CompilationUnit> parse(final InputStream in) {
+        return parse(in, configuration.getCharacterEncoding());
     }
 
     /**
@@ -181,23 +168,28 @@
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      * @throws FileNotFoundException the file was not found
+     * @deprecated set the encoding in the {@link ParserConfiguration}
      */
-    public static CompilationUnit parse(final File file, final Charset encoding) throws FileNotFoundException {
-        return simplifiedParse(COMPILATION_UNIT, provider(file, encoding)).setStorage(file.toPath());
+    @Deprecated
+    public ParseResult<CompilationUnit> parse(final File file, final Charset encoding) throws FileNotFoundException {
+        ParseResult<CompilationUnit> result = parse(COMPILATION_UNIT, provider(file, encoding));
+        result.getResult().ifPresent(cu -> cu.setStorage(file.toPath(), encoding));
+        return result;
     }
 
     /**
      * Parses the Java code contained in a {@link File} and returns a
      * {@link CompilationUnit} that represents it.<br>
-     * Note: Uses UTF-8 encoding
      *
      * @param file {@link File} containing Java source code. It will be closed after parsing.
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      * @throws FileNotFoundException the file was not found
      */
-    public static CompilationUnit parse(final File file) throws FileNotFoundException {
-        return simplifiedParse(COMPILATION_UNIT, provider(file)).setStorage(file.toPath());
+    public ParseResult<CompilationUnit> parse(final File file) throws FileNotFoundException {
+        ParseResult<CompilationUnit> result = parse(COMPILATION_UNIT, provider(file, configuration.getCharacterEncoding()));
+        result.getResult().ifPresent(cu -> cu.setStorage(file.toPath(), configuration.getCharacterEncoding()));
+        return result;
     }
 
     /**
@@ -209,29 +201,33 @@
      * @return CompilationUnit representing the Java source code
      * @throws IOException the path could not be accessed
      * @throws ParseProblemException if the source code has parser errors
+     * @deprecated set the encoding in the {@link ParserConfiguration}
      */
-    public static CompilationUnit parse(final Path path, final Charset encoding) throws IOException {
-        return simplifiedParse(COMPILATION_UNIT, provider(path, encoding)).setStorage(path);
+    @Deprecated
+    public ParseResult<CompilationUnit> parse(final Path path, final Charset encoding) throws IOException {
+        ParseResult<CompilationUnit> result = parse(COMPILATION_UNIT, provider(path, encoding));
+        result.getResult().ifPresent(cu -> cu.setStorage(path, encoding));
+        return result;
     }
 
     /**
      * Parses the Java code contained in a file and returns a
      * {@link CompilationUnit} that represents it.<br>
-     * Note: Uses UTF-8 encoding
      *
      * @param path path to a file containing Java source code
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      * @throws IOException the path could not be accessed
      */
-    public static CompilationUnit parse(final Path path) throws IOException {
-        return simplifiedParse(COMPILATION_UNIT, provider(path)).setStorage(path);
+    public ParseResult<CompilationUnit> parse(final Path path) throws IOException {
+        ParseResult<CompilationUnit> result = parse(COMPILATION_UNIT, provider(path, configuration.getCharacterEncoding()));
+        result.getResult().ifPresent(cu -> cu.setStorage(path, configuration.getCharacterEncoding()));
+        return result;
     }
 
     /**
      * Parses the Java code contained in a resource and returns a
      * {@link CompilationUnit} that represents it.<br>
-     * Note: Uses UTF-8 encoding
      *
      * @param path path to a resource containing Java source code. As resource is accessed through a class loader, a
      * leading "/" is not allowed in pathToResource
@@ -239,8 +235,8 @@
      * @throws ParseProblemException if the source code has parser errors
      * @throws IOException the path could not be accessed
      */
-    public static CompilationUnit parseResource(final String path) throws IOException {
-        return simplifiedParse(COMPILATION_UNIT, resourceProvider(path));
+    public ParseResult<CompilationUnit> parseResource(final String path) throws IOException {
+        return parse(COMPILATION_UNIT, resourceProvider(path, configuration.getCharacterEncoding()));
     }
 
     /**
@@ -253,9 +249,11 @@
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      * @throws IOException the path could not be accessed
+     * @deprecated set the encoding in the {@link ParserConfiguration}
      */
-    public static CompilationUnit parseResource(final String path, Charset encoding) throws IOException {
-        return simplifiedParse(COMPILATION_UNIT, resourceProvider(path, encoding));
+    @Deprecated
+    public ParseResult<CompilationUnit> parseResource(final String path, Charset encoding) throws IOException {
+        return parse(COMPILATION_UNIT, resourceProvider(path, encoding));
     }
 
     /**
@@ -268,9 +266,11 @@
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      * @throws IOException the path could not be accessed
+     * @deprecated set the encoding in the {@link ParserConfiguration}
      */
-    public static CompilationUnit parseResource(final ClassLoader classLoader, final String path, Charset encoding) throws IOException {
-        return simplifiedParse(COMPILATION_UNIT, resourceProvider(classLoader, path, encoding));
+    @Deprecated
+    public ParseResult<CompilationUnit> parseResource(final ClassLoader classLoader, final String path, Charset encoding) throws IOException {
+        return parse(COMPILATION_UNIT, resourceProvider(classLoader, path, encoding));
     }
 
     /**
@@ -281,8 +281,8 @@
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static CompilationUnit parse(final Reader reader) {
-        return simplifiedParse(COMPILATION_UNIT, provider(reader));
+    public ParseResult<CompilationUnit> parse(final Reader reader) {
+        return parse(COMPILATION_UNIT, provider(reader));
     }
 
     /**
@@ -293,8 +293,8 @@
      * @return CompilationUnit representing the Java source code
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static CompilationUnit parse(String code) {
-        return simplifiedParse(COMPILATION_UNIT, provider(code));
+    public ParseResult<CompilationUnit> parse(String code) {
+        return parse(COMPILATION_UNIT, provider(code));
     }
 
     /**
@@ -305,8 +305,8 @@
      * @return BlockStmt representing the Java block
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static BlockStmt parseBlock(final String blockStatement) {
-        return simplifiedParse(BLOCK, provider(blockStatement));
+    public ParseResult<BlockStmt> parseBlock(final String blockStatement) {
+        return parse(BLOCK, provider(blockStatement));
     }
 
     /**
@@ -317,16 +317,8 @@
      * @return Statement representing the Java statement
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static Statement parseStatement(final String statement) {
-        return simplifiedParse(STATEMENT, provider(statement));
-    }
-
-    private static <T extends Node> T simplifiedParse(ParseStart<T> context, Provider provider) {
-        ParseResult<T> result = new JavaParser(staticConfiguration).parse(context, provider);
-        if (result.isSuccessful()) {
-            return result.getResult().get();
-        }
-        throw new ParseProblemException(result.getProblems());
+    public ParseResult<Statement> parseStatement(final String statement) {
+        return parse(STATEMENT, provider(statement));
     }
 
     /**
@@ -337,8 +329,8 @@
      * @return ImportDeclaration representing the Java import declaration
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static ImportDeclaration parseImport(final String importDeclaration) {
-        return simplifiedParse(IMPORT_DECLARATION, provider(importDeclaration));
+    public ParseResult<ImportDeclaration> parseImport(final String importDeclaration) {
+        return parse(IMPORT_DECLARATION, provider(importDeclaration));
     }
 
     /**
@@ -350,8 +342,8 @@
      * @throws ParseProblemException if the source code has parser errors
      */
     @SuppressWarnings("unchecked")
-    public static <T extends Expression> T parseExpression(final String expression) {
-        return (T) simplifiedParse(EXPRESSION, provider(expression));
+    public <T extends Expression> ParseResult<T> parseExpression(final String expression) {
+        return (ParseResult<T>) parse(EXPRESSION, provider(expression));
     }
 
     /**
@@ -362,8 +354,8 @@
      * @return AnnotationExpr representing the Java annotation
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static AnnotationExpr parseAnnotation(final String annotation) {
-        return simplifiedParse(ANNOTATION, provider(annotation));
+    public ParseResult<AnnotationExpr> parseAnnotation(final String annotation) {
+        return parse(ANNOTATION, provider(annotation));
     }
 
     /**
@@ -374,36 +366,8 @@
      * @return BodyDeclaration representing the Java annotation
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static BodyDeclaration<?> parseAnnotationBodyDeclaration(final String body) {
-        return simplifiedParse(ANNOTATION_BODY, provider(body));
-    }
-
-    /**
-     * Parses a Java class body declaration(e.g fields or methods) and returns a
-     * {@link BodyDeclaration} that represents it.
-     *
-     * @param body the body of a class
-     * @return BodyDeclaration representing the Java class body
-     * @throws ParseProblemException if the source code has parser errors
-     * @deprecated just use parseBodyDeclaration now.
-     */
-    @Deprecated
-    public static BodyDeclaration<?> parseClassBodyDeclaration(String body) {
-        return parseBodyDeclaration(body);
-    }
-
-    /**
-     * Parses a Java interface body declaration(e.g fields or methods) and returns a
-     * {@link BodyDeclaration} that represents it.
-     *
-     * @param body the body of an interface
-     * @return BodyDeclaration representing the Java interface body
-     * @throws ParseProblemException if the source code has parser errors
-     * @deprecated just use parseBodyDeclaration now.
-     */
-    @Deprecated
-    public static BodyDeclaration<?> parseInterfaceBodyDeclaration(String body) {
-        return parseBodyDeclaration(body);
+    public ParseResult<BodyDeclaration<?>> parseAnnotationBodyDeclaration(final String body) {
+        return parse(ANNOTATION_BODY, provider(body));
     }
 
     /**
@@ -414,8 +378,8 @@
      * @return BodyDeclaration representing the Java interface body
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static BodyDeclaration<?> parseBodyDeclaration(String body) {
-        return simplifiedParse(CLASS_BODY, provider(body));
+    public ParseResult<BodyDeclaration<?>> parseBodyDeclaration(String body) {
+        return parse(CLASS_BODY, provider(body));
     }
 
     /**
@@ -425,8 +389,8 @@
      * @return ClassOrInterfaceType representing the type
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static ClassOrInterfaceType parseClassOrInterfaceType(String type) {
-        return simplifiedParse(CLASS_OR_INTERFACE_TYPE, provider(type));
+    public ParseResult<ClassOrInterfaceType> parseClassOrInterfaceType(String type) {
+        return parse(CLASS_OR_INTERFACE_TYPE, provider(type));
     }
 
     /**
@@ -436,8 +400,8 @@
      * @return ClassOrInterfaceType representing the type
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static Type parseType(String type) {
-        return simplifiedParse(TYPE, provider(type));
+    public ParseResult<Type> parseType(String type) {
+        return parse(TYPE, provider(type));
     }
 
     /**
@@ -448,20 +412,8 @@
      * @return VariableDeclarationExpr representing the type
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static VariableDeclarationExpr parseVariableDeclarationExpr(String declaration) {
-        return simplifiedParse(VARIABLE_DECLARATION_EXPR, provider(declaration));
-    }
-
-    /**
-     * Parses the content of a JavadocComment and returns a {@link com.github.javaparser.javadoc.Javadoc} that
-     * represents it.
-     *
-     * @param content a variable declaration like <code>content of my javadoc\n * second line\n * third line</code>
-     * @return Javadoc representing the content of the comment
-     * @throws ParseProblemException if the source code has parser errors
-     */
-    public static Javadoc parseJavadoc(String content) {
-        return JavadocParser.parse(content);
+    public ParseResult<VariableDeclarationExpr> parseVariableDeclarationExpr(String declaration) {
+        return parse(VARIABLE_DECLARATION_EXPR, provider(declaration));
     }
 
     /**
@@ -471,8 +423,8 @@
      * @return the AST for the statement.
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static ExplicitConstructorInvocationStmt parseExplicitConstructorInvocationStmt(String statement) {
-        return simplifiedParse(EXPLICIT_CONSTRUCTOR_INVOCATION_STMT, provider(statement));
+    public ParseResult<ExplicitConstructorInvocationStmt> parseExplicitConstructorInvocationStmt(String statement) {
+        return parse(EXPLICIT_CONSTRUCTOR_INVOCATION_STMT, provider(statement));
     }
 
     /**
@@ -482,8 +434,8 @@
      * @return the AST for the name
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static Name parseName(String qualifiedName) {
-        return simplifiedParse(NAME, provider(qualifiedName));
+    public ParseResult<Name> parseName(String qualifiedName) {
+        return parse(NAME, provider(qualifiedName));
     }
 
     /**
@@ -493,8 +445,8 @@
      * @return the AST for the name
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static SimpleName parseSimpleName(String name) {
-        return simplifiedParse(SIMPLE_NAME, provider(name));
+    public ParseResult<SimpleName> parseSimpleName(String name) {
+        return parse(SIMPLE_NAME, provider(name));
     }
 
     /**
@@ -504,11 +456,10 @@
      * @return the AST for the parameter
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static Parameter parseParameter(String parameter) {
-        return simplifiedParse(PARAMETER, provider(parameter));
+    public ParseResult<Parameter> parseParameter(String parameter) {
+        return parse(PARAMETER, provider(parameter));
     }
 
-
     /**
      * Parses a package declaration and returns it as a PackageDeclaration.
      *
@@ -516,7 +467,55 @@
      * @return the AST for the parameter
      * @throws ParseProblemException if the source code has parser errors
      */
-    public static PackageDeclaration parsePackageDeclaration(String packageDeclaration) {
-        return simplifiedParse(PACKAGE_DECLARATION, provider(packageDeclaration));
+    public ParseResult<PackageDeclaration> parsePackageDeclaration(String packageDeclaration) {
+        return parse(PACKAGE_DECLARATION, provider(packageDeclaration));
     }
+
+    /**
+     * Parses a type declaration and returns it as a TypeDeclaration.
+     *
+     * @param typeDeclaration a declaration like "class X {}"
+     * @return the AST for the type declaration
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public ParseResult<TypeDeclaration<?>> parseTypeDeclaration(String typeDeclaration) {
+        return parse(TYPE_DECLARATION, provider(typeDeclaration));
+    }
+
+    /**
+     * Parses a module declaration and returns it as a ModuleDeclaration.
+     *
+     * @param moduleDeclaration a declaration like "module X {}"
+     * @return the AST for the module declaration
+     * @throws ParseProblemException if the source code has parser errors
+     * @see ModuleDeclaration
+     */
+    public ParseResult<ModuleDeclaration> parseModuleDeclaration(String moduleDeclaration) {
+        return parse(MODULE_DECLARATION, provider(moduleDeclaration));
+    }
+
+    /**
+     * Parses a module directive and returns it as a ModuleDirective.
+     *
+     * @param moduleDirective a directive like "opens C;"
+     * @return the AST for the module directive
+     * @throws ParseProblemException if the source code has parser errors
+     * @see ModuleDirective
+     */
+    public ParseResult<ModuleDirective> parseModuleDirective(String moduleDirective) {
+        return parse(MODULE_DIRECTIVE, provider(moduleDirective));
+    }
+
+
+    /**
+     * Parses a type parameter and returns it as a TypeParameter
+     *
+     * @param typeParameter a parameter like "T extends Serializable"
+     * @return the AST for the type parameter
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public ParseResult<TypeParameter> parseTypeParameter(String typeParameter) {
+        return parse(TYPE_PARAMETER, provider(typeParameter));
+    }
+
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/JavaToken.java b/javaparser-core/src/main/java/com/github/javaparser/JavaToken.java
index ad56ff5..e988b0b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/JavaToken.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/JavaToken.java
@@ -25,7 +25,7 @@
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import static com.github.javaparser.utils.Utils.EOL;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A token from a parsed source file.
diff --git a/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java b/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java
index bbe9797..d24cad4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/JavadocParser.java
@@ -32,15 +32,15 @@
 import java.util.stream.Collectors;
 
 import static com.github.javaparser.utils.Utils.*;
-import static com.github.javaparser.utils.Utils.nextWord;
 
 /**
- * The class responsible for parsing the content of JavadocComments and produce JavadocDocuments.
+ * The class responsible for parsing the content of JavadocComments and producing JavadocDocuments.
+ * <a href="https://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/javadoc.html">The Javadoc specification.</a>
  */
 class JavadocParser {
 
     private static String BLOCK_TAG_PREFIX = "@";
-    private static Pattern BLOCK_PATTERN = Pattern.compile("^" + BLOCK_TAG_PREFIX, Pattern.MULTILINE);
+    private static Pattern BLOCK_PATTERN = Pattern.compile("^\\s*" + BLOCK_TAG_PREFIX, Pattern.MULTILINE);
 
     public static Javadoc parse(JavadocComment comment) {
         return parse(comment.getContent());
@@ -72,7 +72,7 @@
             //then needs to be added again so that the block parsers handles everything correctly.
             blockLines = BLOCK_PATTERN
                 .splitAsStream(tagBlock)
-                .filter(STRING_NOT_EMPTY)
+                .filter(s1 -> !s1.isEmpty())
                 .map(s -> BLOCK_TAG_PREFIX + s)
                 .collect(Collectors.toList());
         }
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 4edc79a..4b2620e 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ParseResult.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ParseResult.java
@@ -36,7 +36,6 @@
 public class ParseResult<T> {
     private final T result;
     private final List<Problem> problems;
-    private final List<JavaToken> tokens;
     private final CommentsCollection commentsCollection;
 
     /**
@@ -44,13 +43,11 @@
      *
      * @param result the AST, or empty if it wasn't created.
      * @param problems a list of encountered parsing problems.
-     * @param tokens the complete list of tokens that were parsed, or empty if parsing failed completely.
      */
-    public ParseResult(T result, List<Problem> problems, List<JavaToken> tokens, CommentsCollection commentsCollection) {
+    public ParseResult(T result, List<Problem> problems, CommentsCollection commentsCollection) {
         this.commentsCollection = commentsCollection;
         this.result = result;
         this.problems = problems;
-        this.tokens = tokens;
     }
 
     /**
@@ -84,16 +81,6 @@
     }
 
     /**
-     * @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()
-     */
-    @Deprecated
-    public Optional<List<JavaToken>> getTokens() {
-        return Optional.ofNullable(tokens);
-    }
-
-    /**
      * @return the complete collection of comments encountered while parsing.
      */
     public Optional<CommentsCollection> getCommentsCollection() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ParseStart.java b/javaparser-core/src/main/java/com/github/javaparser/ParseStart.java
index ecb562c..9e1f143 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ParseStart.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ParseStart.java
@@ -26,12 +26,16 @@
 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.body.TypeDeclaration;
 import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.modules.ModuleDeclaration;
+import com.github.javaparser.ast.modules.ModuleDirective;
 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.type.TypeParameter;
 
 /**
  * The start production for JavaParser.
@@ -54,12 +58,16 @@
     ParseStart<BodyDeclaration<?>> CLASS_BODY = GeneratedJavaParser::ClassOrInterfaceBodyDeclarationParseStart;
     ParseStart<ClassOrInterfaceType> CLASS_OR_INTERFACE_TYPE = GeneratedJavaParser::ClassOrInterfaceTypeParseStart;
     ParseStart<Type> TYPE = GeneratedJavaParser::ResultTypeParseStart;
+    ParseStart<TypeParameter> TYPE_PARAMETER = GeneratedJavaParser::TypeParameterParseStart;
     ParseStart<VariableDeclarationExpr> VARIABLE_DECLARATION_EXPR = GeneratedJavaParser::VariableDeclarationExpressionParseStart;
     ParseStart<ExplicitConstructorInvocationStmt> EXPLICIT_CONSTRUCTOR_INVOCATION_STMT = GeneratedJavaParser::ExplicitConstructorInvocationParseStart;
     ParseStart<Name> NAME = GeneratedJavaParser::NameParseStart;
     ParseStart<SimpleName> SIMPLE_NAME = GeneratedJavaParser::SimpleNameParseStart;
     ParseStart<Parameter> PARAMETER = GeneratedJavaParser::ParameterParseStart;
     ParseStart<PackageDeclaration> PACKAGE_DECLARATION = GeneratedJavaParser::PackageDeclarationParseStart;
+    ParseStart<TypeDeclaration<?>> TYPE_DECLARATION = GeneratedJavaParser::TypeDeclarationParseStart;
+    ParseStart<ModuleDeclaration> MODULE_DECLARATION = GeneratedJavaParser::ModuleDeclarationParseStart;
+    ParseStart<ModuleDirective> MODULE_DIRECTIVE = GeneratedJavaParser::ModuleDirectiveParseStart;
 
     R parse(GeneratedJavaParser parser) throws ParseException;
 }
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 e5be2b8..73e87eb 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ParserConfiguration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ParserConfiguration.java
@@ -21,20 +21,39 @@
 
 package com.github.javaparser;
 
-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 com.github.javaparser.version.Java11PostProcessor;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
+import static com.github.javaparser.utils.Utils.*;
 
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
-import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.ParseResult.PostProcessor;
+import com.github.javaparser.Providers.PreProcessor;
+import com.github.javaparser.UnicodeEscapeProcessingProvider.PositionMapping;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.validator.Java10Validator;
+import com.github.javaparser.ast.validator.Java11Validator;
+import com.github.javaparser.ast.validator.Java12Validator;
+import com.github.javaparser.ast.validator.Java1_0Validator;
+import com.github.javaparser.ast.validator.Java1_1Validator;
+import com.github.javaparser.ast.validator.Java1_2Validator;
+import com.github.javaparser.ast.validator.Java1_3Validator;
+import com.github.javaparser.ast.validator.Java1_4Validator;
+import com.github.javaparser.ast.validator.Java5Validator;
+import com.github.javaparser.ast.validator.Java6Validator;
+import com.github.javaparser.ast.validator.Java7Validator;
+import com.github.javaparser.ast.validator.Java8Validator;
+import com.github.javaparser.ast.validator.Java9Validator;
+import com.github.javaparser.ast.validator.ProblemReporter;
+import com.github.javaparser.ast.validator.Validator;
+import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
+import com.github.javaparser.resolution.SymbolResolver;
+import com.github.javaparser.version.Java10PostProcessor;
+import com.github.javaparser.version.Java11PostProcessor;
+import com.github.javaparser.version.Java12PostProcessor;
 
 /**
  * The configuration that is used by the parser.
@@ -43,38 +62,74 @@
  */
 public class ParserConfiguration {
     public enum LanguageLevel {
-        /** Does no post processing or validation. Only for people wanting the fastest parsing. */
+        /**
+         * Does no post processing or validation. Only for people wanting the fastest parsing.
+         */
         RAW(null, null),
-        /** The most used Java version. */
+        /**
+         * The most used Java version.
+         */
         POPULAR(new Java8Validator(), null),
-        /** The latest Java version that is available. */
+        /**
+         * The latest Java version that is available.
+         */
         CURRENT(new Java8Validator(), null),
-        /** The newest Java features supported. */
-        BLEEDING_EDGE(new Java11Validator(), new Java11PostProcessor()),
-        /** Java 1.0 */
+        /**
+         * The newest Java features supported.
+         */
+        BLEEDING_EDGE(new Java12Validator(), new Java12PostProcessor()),
+        /**
+         * Java 1.0
+         */
         JAVA_1_0(new Java1_0Validator(), null),
-        /** Java 1.1 */
+        /**
+         * Java 1.1
+         */
         JAVA_1_1(new Java1_1Validator(), null),
-        /** Java 1.2 */
+        /**
+         * Java 1.2
+         */
         JAVA_1_2(new Java1_2Validator(), null),
-        /** Java 1.3 */
+        /**
+         * Java 1.3
+         */
         JAVA_1_3(new Java1_3Validator(), null),
-        /** Java 1.4 */
+        /**
+         * Java 1.4
+         */
         JAVA_1_4(new Java1_4Validator(), null),
-        /** Java 5 */
+        /**
+         * Java 5
+         */
         JAVA_5(new Java5Validator(), null),
-        /** Java 6 */
+        /**
+         * Java 6
+         */
         JAVA_6(new Java6Validator(), null),
-        /** Java 7 */
+        /**
+         * Java 7
+         */
         JAVA_7(new Java7Validator(), null),
-        /** Java 8 */
+        /**
+         * Java 8
+         */
         JAVA_8(new Java8Validator(), null),
-        /** Java 9 */
+        /**
+         * Java 9
+         */
         JAVA_9(new Java9Validator(), null),
-        /** Java 10 */
+        /**
+         * Java 10
+         */
         JAVA_10(new Java10Validator(), new Java10PostProcessor()),
-        /** Java 11 (work in progress) */
-        JAVA_11_PREVIEW(new Java11Validator(), new Java11PostProcessor());
+        /**
+         * Java 11
+         */
+        JAVA_11(new Java11Validator(), new Java11PostProcessor()),
+        /**
+         * Java 12
+         */
+        JAVA_12(new Java12Validator(), new Java12PostProcessor());
 
         final Validator validator;
         final ParseResult.PostProcessor postProcessor;
@@ -88,20 +143,53 @@
     private boolean storeTokens = true;
     private boolean attributeComments = true;
     private boolean doNotAssignCommentsPrecedingEmptyLines = true;
-    private boolean doNotConsiderAnnotationsAsNodeStartForCodeAttribution = false;
+    private boolean ignoreAnnotationsWhenAttributingComments = false;
     private boolean lexicalPreservationEnabled = false;
+    private boolean preprocessUnicodeEscapes = false;
     private SymbolResolver symbolResolver = null;
     private int tabSize = 1;
     private LanguageLevel languageLevel = CURRENT;
+    private Charset characterEncoding = Providers.UTF8;
 
+    private final List<Providers.PreProcessor> preProcessors = new ArrayList<>();
     private final List<ParseResult.PostProcessor> postProcessors = new ArrayList<>();
 
     public ParserConfiguration() {
+    	class UnicodeEscapeProcessor implements PreProcessor, PostProcessor {
+    		private UnicodeEscapeProcessingProvider _unicodeDecoder;
+
+			@Override
+    		public Provider process(Provider innerProvider) {
+	            if (isPreprocessUnicodeEscapes()) {
+	                _unicodeDecoder = new UnicodeEscapeProcessingProvider(innerProvider);
+					return _unicodeDecoder;
+	            }
+	            return innerProvider;
+    		}
+    		
+			@Override
+			public void process(ParseResult<? extends Node> result,
+					ParserConfiguration configuration) {
+				if (isPreprocessUnicodeEscapes()) {
+					result.getResult().ifPresent(
+						root -> {
+							PositionMapping mapping = _unicodeDecoder.getPositionMapping();
+							if (!mapping.isEmpty()) {
+								root.walk(
+									node -> node.getRange().ifPresent(
+										range -> node.setRange(mapping.transform(range))));
+							}
+						}
+					);
+				}
+			}
+    	}
+    	UnicodeEscapeProcessor unicodeProcessor = new UnicodeEscapeProcessor();
+    	preProcessors.add(unicodeProcessor);
+		postProcessors.add(unicodeProcessor);
         postProcessors.add((result, configuration) -> {
             if (configuration.isLexicalPreservationEnabled()) {
-                if (configuration.isLexicalPreservationEnabled()) {
-                    result.ifSuccessful(LexicalPreservingPrinter::setup);
-                }
+                result.ifSuccessful(LexicalPreservingPrinter::setup);
             }
         });
         postProcessors.add((result, configuration) -> {
@@ -151,12 +239,12 @@
         return this;
     }
 
-    public boolean isDoNotConsiderAnnotationsAsNodeStartForCodeAttribution() {
-        return doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
+    public boolean isIgnoreAnnotationsWhenAttributingComments() {
+        return ignoreAnnotationsWhenAttributingComments;
     }
 
-    public ParserConfiguration setDoNotConsiderAnnotationsAsNodeStartForCodeAttribution(boolean doNotConsiderAnnotationsAsNodeStartForCodeAttribution) {
-        this.doNotConsiderAnnotationsAsNodeStartForCodeAttribution = doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
+    public ParserConfiguration setIgnoreAnnotationsWhenAttributingComments(boolean ignoreAnnotationsWhenAttributingComments) {
+        this.ignoreAnnotationsWhenAttributingComments = ignoreAnnotationsWhenAttributingComments;
         return this;
     }
 
@@ -186,48 +274,6 @@
     }
 
     /**
-     * @deprecated use getLanguageLevel
-     */
-    @Deprecated
-    public Optional<Validator> getValidator() {
-        throw new IllegalStateException("method is deprecated");
-    }
-
-    /**
-     * @deprecated use setLanguageLevel, or getPostProcessors if you use a custom validator.
-     */
-    @Deprecated
-    public ParserConfiguration setValidator(Validator validator) {
-        // This whole method is a backwards compatability hack.
-        if (validator instanceof Java10Validator) {
-            setLanguageLevel(JAVA_10);
-        } else if (validator instanceof Java9Validator) {
-            setLanguageLevel(JAVA_9);
-        } else if (validator instanceof Java8Validator) {
-            setLanguageLevel(JAVA_8);
-        } else if (validator instanceof Java7Validator) {
-            setLanguageLevel(JAVA_7);
-        } else if (validator instanceof Java6Validator) {
-            setLanguageLevel(JAVA_6);
-        } else if (validator instanceof Java5Validator) {
-            setLanguageLevel(JAVA_5);
-        } else if (validator instanceof Java1_4Validator) {
-            setLanguageLevel(JAVA_1_4);
-        } else if (validator instanceof Java1_3Validator) {
-            setLanguageLevel(JAVA_1_3);
-        } else if (validator instanceof Java1_2Validator) {
-            setLanguageLevel(JAVA_1_2);
-        } else if (validator instanceof Java1_1Validator) {
-            setLanguageLevel(JAVA_1_1);
-        } else if (validator instanceof Java1_0Validator) {
-            setLanguageLevel(JAVA_1_0);
-        } else if (validator instanceof NoProblemsValidator) {
-            setLanguageLevel(RAW);
-        }
-        return this;
-    }
-
-    /**
      * Disabled by default.
      * When this is enabled, LexicalPreservingPrinter.print can be used to reproduce
      * the original formatting of the file.
@@ -256,6 +302,10 @@
         return this;
     }
 
+    public List<Providers.PreProcessor> getPreProcessors() {
+        return preProcessors;
+    }
+
     public List<ParseResult.PostProcessor> getPostProcessors() {
         return postProcessors;
     }
@@ -268,4 +318,33 @@
     public LanguageLevel getLanguageLevel() {
         return languageLevel;
     }
+
+    /**
+     * When set to true, unicode escape handling is done by preprocessing the whole input,
+     * meaning that all unicode escapes are turned into unicode characters before parsing.
+     * That means the AST will never contain literal unicode escapes. However,
+     * positions in the AST will point to the original input, which is exactly the same as without this option.
+     * Without this option enabled, the unicode escapes will not be processed and are transfered intact to the AST.
+     */
+    public ParserConfiguration setPreprocessUnicodeEscapes(boolean preprocessUnicodeEscapes) {
+        this.preprocessUnicodeEscapes = preprocessUnicodeEscapes;
+        return this;
+    }
+
+    public boolean isPreprocessUnicodeEscapes() {
+        return preprocessUnicodeEscapes;
+    }
+
+    public Charset getCharacterEncoding() {
+        return characterEncoding;
+    }
+
+    /**
+     * The character encoding used for reading input from files and streams. By default UTF8 is used.
+     */
+    public ParserConfiguration setCharacterEncoding(Charset characterEncoding) {
+        this.characterEncoding = characterEncoding;
+        return this;
+    }
+
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/Position.java b/javaparser-core/src/main/java/com/github/javaparser/Position.java
index 78e95d8..49afe45 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/Position.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/Position.java
@@ -64,6 +64,20 @@
     }
 
     /**
+     * @return a position that is "characters" characters more to the right than this position.
+     */
+    public Position right(int characters) {
+        return new Position(line, this.column + characters);
+    }
+
+    /**
+     * @return a position that is on the start of the next line from this position.
+     */
+    public Position nextLine() {
+        return new Position(line + 1, HOME.column);
+    }
+
+    /**
      * Check if the position is usable. Does not know what it is pointing at, so it can't check if the position is after
      * the end of the source.
      */
diff --git a/javaparser-core/src/main/java/com/github/javaparser/Problem.java b/javaparser-core/src/main/java/com/github/javaparser/Problem.java
index 2fc0532..c1316e3 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/Problem.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/Problem.java
@@ -80,14 +80,6 @@
     }
 
     /**
-     * @deprecated use getLocation()
-     */
-    @Deprecated
-    public Optional<TokenRange> getRange() {
-        return getLocation();
-    }
-
-    /**
      * @return the cause that was passed into the constructor.
      */
     public Optional<Throwable> getCause() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/Providers.java b/javaparser-core/src/main/java/com/github/javaparser/Providers.java
index f4b3df9..e1ce0e1 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/Providers.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/Providers.java
@@ -108,4 +108,7 @@
         return resourceProvider(pathToResource, UTF8);
     }
 
+    public interface PreProcessor {
+        Provider process(Provider innerProvider);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/Range.java b/javaparser-core/src/main/java/com/github/javaparser/Range.java
index dc5b329..67c4ddd 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/Range.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/Range.java
@@ -80,15 +80,36 @@
         return (begin.isBefore(other.begin) || begin.equals(other.begin)) &&
                 (end.isAfter(other.end) || end.equals(other.end));
     }
-
+    
     /**
-     * Do this strictly contains other? It means that this has to be larger than other and it has to start as other
-     * or before and end as other or after.
+     * As strictlyContains, but a position that matches the begin or the end of this range is also considered contained one in each other.
+     */
+    public boolean contains(Position position) {
+        return strictlyContains(position) || begin.equals(position) || end.equals(position);
+    }
+    
+    /**
+     * Does this strictly contain other? It means that this has to be larger than other and it has to start before
+     * other and end after other.
      */
     public boolean strictlyContains(Range other) {
         return begin.isBefore(other.begin) && end.isAfter(other.end);
     }
-
+    
+    /**
+     * Does this strictly contain position. It means that the position is after the begin of this range and before the end of this range.
+     */
+    public boolean strictlyContains(Position position) {
+        return position.isAfter(begin) && position.isBefore(end);
+    }
+    
+    /**
+     * Checks whether this Range overlaps with another Range. If two ranges overlap, this range or the other range strictlyContains the begin or the end of the other range.
+     */
+    public boolean overlapsWith(Range other) {
+		return strictlyContains(other.begin) || strictlyContains(other.end) || other.strictlyContains(begin) || other.strictlyContains(end);
+	}
+    
     public boolean isBefore(Position position) {
         return end.isBefore(position);
     }
@@ -101,11 +122,9 @@
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-
+		
         Range range = (Range) o;
-
         return begin.equals(range.begin) && end.equals(range.end);
-
     }
 
     @Override
@@ -117,4 +136,8 @@
     public String toString() {
         return begin + "-" + end;
     }
+
+    public int getLineCount() {
+        return end.line - begin.line + 1;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/StaticJavaParser.java b/javaparser-core/src/main/java/com/github/javaparser/StaticJavaParser.java
new file mode 100644
index 0000000..cee8646
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/StaticJavaParser.java
@@ -0,0 +1,470 @@
+/*
+ * 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;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.ImportDeclaration;
+import com.github.javaparser.ast.Node;
+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.body.TypeDeclaration;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.modules.ModuleDeclaration;
+import com.github.javaparser.ast.modules.ModuleDirective;
+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.type.TypeParameter;
+import com.github.javaparser.javadoc.Javadoc;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+
+/**
+ * A simpler, static API than {@link JavaParser}.
+ */
+public final class StaticJavaParser {
+    private static ParserConfiguration configuration = new ParserConfiguration();
+
+    private StaticJavaParser() {
+    }
+
+    /**
+     * Get the configuration for the parse... methods.
+     */
+    public static ParserConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    /**
+     * Set the configuration for the static parse... methods.
+     * This is a STATIC field, so modifying it will directly change how all static parse... methods work!
+     */
+    public static void setConfiguration(ParserConfiguration configuration) {
+        StaticJavaParser.configuration = configuration;
+    }
+
+    private static JavaParser newParser() {
+        return new JavaParser(configuration);
+    }
+
+    /**
+     * Parses the Java code contained in the {@link InputStream} and returns a
+     * {@link CompilationUnit} that represents it.
+     *
+     * @param in {@link InputStream} containing Java source code. It will be closed after parsing.
+     * @param encoding encoding of the source code
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     * @deprecated set the encoding in the {@link ParserConfiguration}
+     */
+    @Deprecated
+    public static CompilationUnit parse(final InputStream in, Charset encoding) {
+        return handleResult(newParser().parse(in, encoding));
+    }
+
+    /**
+     * Parses the Java code contained in the {@link InputStream} and returns a
+     * {@link CompilationUnit} that represents it.<br>
+     *
+     * @param in {@link InputStream} containing Java source code. It will be closed after parsing.
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static CompilationUnit parse(final InputStream in) {
+        return handleResult(newParser().parse(in));
+    }
+
+    /**
+     * Parses the Java code contained in a {@link File} and returns a
+     * {@link CompilationUnit} that represents it.
+     *
+     * @param file {@link File} containing Java source code. It will be closed after parsing.
+     * @param encoding encoding of the source code
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     * @throws FileNotFoundException the file was not found
+     * @deprecated set the encoding in the {@link ParserConfiguration}
+     */
+    @Deprecated
+    public static CompilationUnit parse(final File file, final Charset encoding) throws FileNotFoundException {
+        return handleResult(newParser().parse(file, encoding));
+    }
+
+    /**
+     * Parses the Java code contained in a {@link File} and returns a
+     * {@link CompilationUnit} that represents it.<br>
+     *
+     * @param file {@link File} containing Java source code. It will be closed after parsing.
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     * @throws FileNotFoundException the file was not found
+     */
+    public static CompilationUnit parse(final File file) throws FileNotFoundException {
+        return handleResult(newParser().parse(file));
+    }
+
+    /**
+     * Parses the Java code contained in a file and returns a
+     * {@link CompilationUnit} that represents it.
+     *
+     * @param path path to a file containing Java source code
+     * @param encoding encoding of the source code
+     * @return CompilationUnit representing the Java source code
+     * @throws IOException the path could not be accessed
+     * @throws ParseProblemException if the source code has parser errors
+     * @deprecated set the encoding in the {@link ParserConfiguration}
+     */
+    @Deprecated
+    public static CompilationUnit parse(final Path path, final Charset encoding) throws IOException {
+        return handleResult(newParser().parse(path, encoding));
+    }
+
+    /**
+     * Parses the Java code contained in a file and returns a
+     * {@link CompilationUnit} that represents it.<br>
+     *
+     * @param path path to a file containing Java source code
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     * @throws IOException the path could not be accessed
+     */
+    public static CompilationUnit parse(final Path path) throws IOException {
+        return handleResult(newParser().parse(path));
+    }
+
+    /**
+     * Parses the Java code contained in a resource and returns a
+     * {@link CompilationUnit} that represents it.<br>
+     *
+     * @param path path to a resource containing Java source code. As resource is accessed through a class loader, a
+     * leading "/" is not allowed in pathToResource
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     * @throws IOException the path could not be accessed
+     */
+    public static CompilationUnit parseResource(final String path) throws IOException {
+        return handleResult(newParser().parseResource(path));
+    }
+
+    /**
+     * Parses the Java code contained in a resource and returns a
+     * {@link CompilationUnit} that represents it.<br>
+     *
+     * @param path path to a resource containing Java source code. As resource is accessed through a class loader, a
+     * leading "/" is not allowed in pathToResource
+     * @param encoding encoding of the source code
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     * @throws IOException the path could not be accessed
+     * @deprecated set the encoding in the {@link ParserConfiguration}
+     */
+    @Deprecated
+    public static CompilationUnit parseResource(final String path, Charset encoding) throws IOException {
+        return handleResult(newParser().parseResource(path, encoding));
+    }
+
+    /**
+     * Parses the Java code contained in a resource and returns a
+     * {@link CompilationUnit} that represents it.<br>
+     *
+     * @param classLoader the classLoader that is asked to load the resource
+     * @param path path to a resource containing Java source code. As resource is accessed through a class loader, a
+     * leading "/" is not allowed in pathToResource
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     * @throws IOException the path could not be accessed
+     * @deprecated set the encoding in the {@link ParserConfiguration}
+     */
+    @Deprecated
+    public static CompilationUnit parseResource(final ClassLoader classLoader, final String path, Charset encoding) throws IOException {
+        return handleResult(newParser().parseResource(classLoader, path, encoding));
+    }
+
+    /**
+     * Parses Java code from a Reader and returns a
+     * {@link CompilationUnit} that represents it.<br>
+     *
+     * @param reader the reader containing Java source code. It will be closed after parsing.
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static CompilationUnit parse(final Reader reader) {
+        return handleResult(newParser().parse(reader));
+    }
+
+    /**
+     * Parses the Java code contained in code and returns a
+     * {@link CompilationUnit} that represents it.
+     *
+     * @param code Java source code
+     * @return CompilationUnit representing the Java source code
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static CompilationUnit parse(String code) {
+        return handleResult(newParser().parse(code));
+    }
+
+    /**
+     * Parses the Java block contained in a {@link String} and returns a
+     * {@link BlockStmt} that represents it.
+     *
+     * @param blockStatement {@link String} containing Java block code
+     * @return BlockStmt representing the Java block
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static BlockStmt parseBlock(final String blockStatement) {
+        return handleResult(newParser().parseBlock(blockStatement));
+    }
+
+    /**
+     * Parses the Java statement contained in a {@link String} and returns a
+     * {@link Statement} that represents it.
+     *
+     * @param statement {@link String} containing Java statement code
+     * @return Statement representing the Java statement
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static Statement parseStatement(final String statement) {
+        return handleResult(newParser().parseStatement(statement));
+    }
+
+    private static <T extends Node> T handleResult(ParseResult<T> result) {
+        if (result.isSuccessful()) {
+            return result.getResult().get();
+        }
+        throw new ParseProblemException(result.getProblems());
+    }
+
+    /**
+     * Parses the Java import contained in a {@link String} and returns a
+     * {@link ImportDeclaration} that represents it.
+     *
+     * @param importDeclaration {@link String} containing Java import code
+     * @return ImportDeclaration representing the Java import declaration
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static ImportDeclaration parseImport(final String importDeclaration) {
+        return handleResult(newParser().parseImport(importDeclaration));
+    }
+
+    /**
+     * Parses the Java expression contained in a {@link String} and returns a
+     * {@link Expression} that represents it.
+     *
+     * @param expression {@link String} containing Java expression
+     * @return Expression representing the Java expression
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static <T extends Expression> T parseExpression(final String expression) {
+        return handleResult(newParser().parseExpression(expression));
+    }
+
+    /**
+     * Parses the Java annotation contained in a {@link String} and returns a
+     * {@link AnnotationExpr} that represents it.
+     *
+     * @param annotation {@link String} containing Java annotation
+     * @return AnnotationExpr representing the Java annotation
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static AnnotationExpr parseAnnotation(final String annotation) {
+        return handleResult(newParser().parseAnnotation(annotation));
+    }
+
+    /**
+     * Parses the Java annotation body declaration(e.g fields or methods) contained in a
+     * {@link String} and returns a {@link BodyDeclaration} that represents it.
+     *
+     * @param body {@link String} containing Java body declaration
+     * @return BodyDeclaration representing the Java annotation
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static BodyDeclaration<?> parseAnnotationBodyDeclaration(final String body) {
+        return handleResult(newParser().parseAnnotationBodyDeclaration(body));
+    }
+
+    /**
+     * Parses a Java class or interface body declaration(e.g fields or methods) and returns a
+     * {@link BodyDeclaration} that represents it.
+     *
+     * @param body the body of a class or interface
+     * @return BodyDeclaration representing the Java interface body
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static BodyDeclaration<?> parseBodyDeclaration(String body) {
+        return handleResult(newParser().parseBodyDeclaration(body));
+    }
+
+    /**
+     * Parses a Java class or interface type name and returns a {@link ClassOrInterfaceType} that represents it.
+     *
+     * @param type the type name like a.b.c.X or Y
+     * @return ClassOrInterfaceType representing the type
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static ClassOrInterfaceType parseClassOrInterfaceType(String type) {
+        return handleResult(newParser().parseClassOrInterfaceType(type));
+    }
+
+    /**
+     * Parses a Java type name and returns a {@link Type} that represents it.
+     *
+     * @param type the type name like a.b.c.X, Y, or int
+     * @return ClassOrInterfaceType representing the type
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static Type parseType(String type) {
+        return handleResult(newParser().parseType(type));
+    }
+
+    /**
+     * Parses a variable declaration expression and returns a {@link VariableDeclarationExpr}
+     * that represents it.
+     *
+     * @param declaration a variable declaration like <code>int x=2;</code>
+     * @return VariableDeclarationExpr representing the type
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static VariableDeclarationExpr parseVariableDeclarationExpr(String declaration) {
+        return handleResult(newParser().parseVariableDeclarationExpr(declaration));
+    }
+
+    /**
+     * Parses the content of a JavadocComment and returns a {@link Javadoc} that
+     * represents it.
+     *
+     * @param content a variable declaration like <code>content of my javadoc\n * second line\n * third line</code>
+     * @return Javadoc representing the content of the comment
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static Javadoc parseJavadoc(String content) {
+        return JavadocParser.parse(content);
+    }
+
+    /**
+     * Parses the this(...) and super(...) statements that may occur at the start of a constructor.
+     *
+     * @param statement a statement like super("hello");
+     * @return the AST for the statement.
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static ExplicitConstructorInvocationStmt parseExplicitConstructorInvocationStmt(String statement) {
+        return handleResult(newParser().parseExplicitConstructorInvocationStmt(statement));
+    }
+
+    /**
+     * Parses a qualified name (one that can have "."s in it) and returns it as a Name.
+     *
+     * @param qualifiedName a name like "com.laamella.parameter_source"
+     * @return the AST for the name
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static Name parseName(String qualifiedName) {
+        return handleResult(newParser().parseName(qualifiedName));
+    }
+
+    /**
+     * Parses a simple name (one that can NOT have "."s in it) and returns it as a SimpleName.
+     *
+     * @param name a name like "parameter_source"
+     * @return the AST for the name
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static SimpleName parseSimpleName(String name) {
+        return handleResult(newParser().parseSimpleName(name));
+    }
+
+    /**
+     * Parses a single parameter (a type and a name) and returns it as a Parameter.
+     *
+     * @param parameter a parameter like "int[] x"
+     * @return the AST for the parameter
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static Parameter parseParameter(String parameter) {
+        return handleResult(newParser().parseParameter(parameter));
+    }
+
+    /**
+     * Parses a package declaration and returns it as a PackageDeclaration.
+     *
+     * @param packageDeclaration a declaration like "package com.microsoft.java;"
+     * @return the AST for the parameter
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static PackageDeclaration parsePackageDeclaration(String packageDeclaration) {
+        return handleResult(newParser().parsePackageDeclaration(packageDeclaration));
+    }
+
+    /**
+     * Parses a type declaration and returns it as a TypeDeclaration.
+     *
+     * @param typeDeclaration a declaration like "class X {}"
+     * @return the AST for the type declaration
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static TypeDeclaration<?> parseTypeDeclaration(String typeDeclaration) {
+        return handleResult(newParser().parseTypeDeclaration(typeDeclaration));
+    }
+
+    /**
+     * Parses a module declaration and returns it as a ModuleDeclaration.
+     *
+     * @param moduleDeclaration a declaration like "module X {}"
+     * @return the AST for the module declaration
+     * @throws ParseProblemException if the source code has parser errors
+     * @see ModuleDeclaration
+     */
+    public static ModuleDeclaration parseModuleDeclaration(String moduleDeclaration) {
+        return handleResult(newParser().parseModuleDeclaration(moduleDeclaration));
+    }
+
+    /**
+     * Parses a module directive and returns it as a ModuleDirective.
+     *
+     * @param moduleDirective a directive like "opens C;"
+     * @return the AST for the module directive
+     * @throws ParseProblemException if the source code has parser errors
+     * @see ModuleDirective
+     */
+    public static ModuleDirective parseModuleDirective(String moduleDirective) {
+        return handleResult(newParser().parseModuleDirective(moduleDirective));
+    }
+
+
+    /**
+     * Parses a type parameter and returns it as a TypeParameter
+     *
+     * @param typeParameter a parameter like "T extends Serializable"
+     * @return the AST for the type parameter
+     * @throws ParseProblemException if the source code has parser errors
+     */
+    public static TypeParameter parseTypeParameter(String typeParameter) {
+        return handleResult(newParser().parseTypeParameter(typeParameter));
+    }
+
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java b/javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java
index 8b90aa7..893e026 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java
@@ -11,14 +11,6 @@
         return getCategory(kind).isWhitespace();
     }
 
-    /**
-     * @deprecated use isEndOfLineToken
-     */
-    @Deprecated
-    public static boolean isEndOfLineCharacter(int kind) {
-        return isEndOfLineToken(kind);
-    }
-
     public static boolean isEndOfLineToken(int kind) {
         return getCategory(kind).isEndOfLine();
     }
@@ -36,14 +28,6 @@
     }
 
     /**
-     * @deprecated use eolTokenKind
-     */
-    @Deprecated
-    public static int eolToken() {
-        return eolTokenKind();
-    }
-
-    /**
      * @return the kind of EOL token to use on the platform you're running on.
      */
     public static int eolTokenKind() {
@@ -67,14 +51,6 @@
     }
 
     /**
-     * @deprecated use spaceTokenKind
-     */
-    @Deprecated
-    public static int spaceToken() {
-        return spaceTokenKind();
-    }
-
-    /**
      * Category of a token, a little more detailed than
      * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.5">The JLS</a>.
      */
diff --git a/javaparser-core/src/main/java/com/github/javaparser/UnicodeEscapeProcessingProvider.java b/javaparser-core/src/main/java/com/github/javaparser/UnicodeEscapeProcessingProvider.java
new file mode 100644
index 0000000..38f8b0c
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/UnicodeEscapeProcessingProvider.java
@@ -0,0 +1,599 @@
+/*

+ * Copyright (C) 2019 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;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.List;

+

+/**

+ * {@link Provider} un-escaping unicode escape sequences in the input sequence.

+ */

+public class UnicodeEscapeProcessingProvider implements Provider {

+	

+	private static final char LF = '\n';

+

+	private static final char CR = '\r';

+

+	private static final char BACKSLASH = '\\';

+

+	private static final int EOF = -1;

+	

+	private char[] _data;

+	

+	/**

+	 * The number of characters in {@link #_data}.

+	 */

+	private int _len = 0;

+	

+	/**

+	 * The position in {@link #_data} where to read the next source character from.

+	 */

+	private int _pos = 0;

+

+	private boolean _backslashSeen;

+	

+	private final LineCounter _inputLine = new LineCounter();

+

+	private final LineCounter _outputLine = new LineCounter();

+	

+	private final PositionMappingBuilder _mappingBuilder = new PositionMappingBuilder(_outputLine, _inputLine);

+	

+	private Provider _input;

+

+	/** 

+	 * Creates a {@link UnicodeEscapeProcessingProvider}.

+	 */

+	public UnicodeEscapeProcessingProvider(Provider input) {

+		this(2048, input);

+	}

+

+	/** 

+	 * Creates a {@link UnicodeEscapeProcessingProvider}.

+	 */

+	public UnicodeEscapeProcessingProvider(int bufferSize, Provider input) {

+		_input = input;

+		_data = new char[bufferSize];

+	}

+	

+	/**

+	 * The {@link LineCounter} of the input file.

+	 */

+	public LineCounter getInputCounter() {

+		return _inputLine;

+	}

+	

+	/**

+	 * The {@link LineCounter} of the output file.

+	 */

+	public LineCounter getOutputCounter() {

+		return _outputLine;

+	}

+

+	@Override

+	public int read(char[] buffer, final int offset, int len) throws IOException {

+		int pos = offset;

+		int stop = offset + len;

+		while (pos < stop) {

+			int ch = _outputLine.process(nextOutputChar());

+			if (ch < 0) {

+				if (pos == offset) {

+					// Nothing read yet, this is the end of the stream.

+					return EOF;

+				} else {

+					break;

+				}

+			} else {

+				_mappingBuilder.update();

+				buffer[pos++] = (char) ch;

+			}

+		}

+		return pos - offset;

+	}

+

+	@Override

+	public void close() throws IOException {

+		_input.close();

+	}

+

+	/** 

+	 * Produces the next un-escaped character to be written to the output.

+	 * 

+	 * @return The next character or <code>-1</code> if no more characters are available.

+	 */

+	private int nextOutputChar() throws IOException {

+		int next = nextInputChar();

+		switch (next) {

+			case EOF:

+				return EOF;

+			case BACKSLASH: {

+				if (_backslashSeen) {

+					return clearBackSlashSeen(next);

+				} else {

+					return backSlashSeen();

+				}

+			}

+			default: {

+				// An arbitrary character.

+				return clearBackSlashSeen(next);

+			}

+		}

+	}

+

+	private int clearBackSlashSeen(int next) {

+		_backslashSeen = false;

+		return next;

+	}

+

+	private int backSlashSeen() throws IOException {

+		_backslashSeen = true;

+		

+		int next = nextInputChar();

+		switch (next) {

+			case EOF:

+				// End of file after backslash produces the backslash itself.

+				return BACKSLASH;

+			case 'u': {

+				return unicodeStartSeen();

+			}

+			default: {

+				pushBack(next);

+				return BACKSLASH;

+			}

+		}

+	}

+

+	private int unicodeStartSeen() throws IOException {

+		int uCnt = 1;

+		while (true) {

+			int next = nextInputChar();

+			switch (next) {

+				case EOF: {

+					pushBackUs(uCnt);

+					return BACKSLASH;

+				}

+				case 'u': {

+					uCnt++;

+					continue;

+				}

+				default: {

+					return readDigits(uCnt, next);

+				}

+			}

+		}

+	}

+

+	private int readDigits(int uCnt, int next3) throws IOException {

+		int digit3 = digit(next3);

+		if (digit3 < 0) {

+			pushBack(next3);

+			pushBackUs(uCnt);

+			return BACKSLASH;

+		}

+		

+		int next2 = nextInputChar();

+		int digit2 = digit(next2);

+		if (digit2 < 0) {

+			pushBack(next2);

+			pushBack(next3);

+			pushBackUs(uCnt);

+			return BACKSLASH;

+		}

+		

+		int next1 = nextInputChar();

+		int digit1 = digit(next1);

+		if (digit1 < 0) {

+			pushBack(next1);

+			pushBack(next2);

+			pushBack(next3);

+			pushBackUs(uCnt);

+			return BACKSLASH;

+		}

+		

+		int next0 = nextInputChar();

+		int digit0 = digit(next0);

+		if (digit0 < 0) {

+			pushBack(next0);

+			pushBack(next1);

+			pushBack(next2);

+			pushBack(next3);

+			pushBackUs(uCnt);

+			return BACKSLASH;

+		}

+

+		int ch = digit3 << 12 | digit2 << 8 | digit1 << 4 | digit0;

+		return clearBackSlashSeen(ch);

+	}

+

+	private void pushBackUs(int cnt) {

+		for (int n = 0; n < cnt; n++) {

+			pushBack('u');

+		}

+	}

+

+	private static int digit(int ch) {

+		if (ch >= '0' && ch <= '9') {

+			return ch - '0';

+		}

+		if (ch >= 'A' && ch <= 'F') {

+			return 10 + ch - 'A';

+		}

+		if (ch >= 'a' && ch <= 'f') {

+			return 10 + ch - 'a';

+		}

+		return -1;

+	}

+

+	/** 

+	 * Processes column/line information from the input file.

+	 * 

+	 * @return The next character or <code>-1</code> if no more input is available.

+	 */

+	private int nextInputChar() throws IOException {

+		int result = nextBufferedChar();

+		return _inputLine.process(result);

+	}

+

+	/** 

+	 * Retrieves the next un-escaped character from the buffered {@link #_input}.

+	 * 

+	 * @return The next character or <code>-1</code> if no more input is available.

+	 */

+	private int nextBufferedChar() throws IOException {

+		while (isBufferEmpty()) {

+			int direct = fillBuffer();

+			if (direct < 0) {

+				return EOF;

+			}

+		}

+		return _data[_pos++];

+	}

+

+	private boolean isBufferEmpty() {

+		return _pos >= _len;

+	}

+

+	private int fillBuffer() throws IOException {

+		_pos = 0;

+		int direct = _input.read(_data, 0, _data.length);

+		if (direct != 0) {

+			_len = direct;

+		}

+		return direct;

+	}

+

+	private void pushBack(int ch) {

+		if (ch < 0) {

+			return;

+		}

+		

+		if (isBufferEmpty()) {

+			_pos = _data.length;

+			_len = _data.length;

+		} else if (_pos == 0) {

+			if (_len == _data.length) {

+				// Buffer is completely full, no push possible, enlarge buffer.

+				char[] newData = new char[_data.length + 1024];

+				_len = newData.length;

+				_pos = newData.length - _data.length;

+				System.arraycopy(_data, 0, newData, _pos, _data.length);

+				_data = newData;

+			} else {

+				// Move contents to the right.

+				int cnt = _len - _pos;

+				_pos = _data.length - _len;

+				_len = _data.length;

+				System.arraycopy(_data, 0, _data, _pos, cnt);

+			}

+		}

+		_data[--_pos] = (char) ch;

+	}

+	

+	/**

+	 * The {@link PositionMapping} being built during processing the file.

+	 */

+	public PositionMapping getPositionMapping() {

+		return _mappingBuilder.getMapping();

+	}

+	

+	/**

+	 * An algorithm mapping {@link Position} form two corresponding files.

+	 */

+	public static final class PositionMapping {

+		

+		private final List<DeltaInfo> _deltas = new ArrayList<>();

+		

+		/** 

+		 * Creates a {@link UnicodeEscapeProcessingProvider.PositionMapping}.

+		 */

+		public PositionMapping() {

+			super();

+		}

+		

+		/**

+		 * Whether this is the identity transformation.

+		 */

+		public boolean isEmpty() {

+			return _deltas.isEmpty();

+		}

+

+		void add(int line, int column, int lineDelta, int columnDelta) {

+			_deltas.add(new DeltaInfo(line, column, lineDelta, columnDelta));

+		}

+		

+		/**

+		 * Looks up the {@link PositionUpdate} for the given Position.

+		 */

+		public PositionUpdate lookup(Position position) {

+			int result = Collections.binarySearch(_deltas, position);

+			if (result >= 0) {

+				return _deltas.get(result);

+			} else {

+				int insertIndex = -result - 1;

+				if (insertIndex == 0) {

+					// Before the first delta info, identity mapping.

+					return PositionUpdate.NONE;

+				} else {

+					// The relevant update is the one with the position smaller

+					// than the requested position.

+					return _deltas.get(insertIndex - 1);

+				}

+			}

+		}

+		

+		/**

+		 * Algorithm updating a {@link Position} from one file to a

+		 * {@link Position} in a corresponding file.

+		 */

+		public static interface PositionUpdate {

+			

+			/**

+			 * The identity position mapping.

+			 */

+			PositionUpdate NONE = new PositionUpdate() {

+				@Override

+				public int transformLine(int line) {

+					return line;

+				}

+				

+				@Override

+				public int transformColumn(int column) {

+					return column;

+				}

+				

+				@Override

+				public Position transform(Position pos) {

+					return pos;

+				}

+			};

+

+			/** 

+			 * Maps the given line to an original line.

+			 */

+			int transformLine(int line);

+

+			/** 

+			 * Maps the given column to an original column.

+			 */

+			int transformColumn(int column);

+

+			/**

+			 * The transformed position.

+			 */

+			default Position transform(Position pos) {

+				int line = pos.line;

+				int column = pos.column;

+				int transformedLine = transformLine(line);

+				int transformedColumn = transformColumn(column);

+				return new Position(transformedLine, transformedColumn);

+			}

+			

+		}

+		

+		private static final class DeltaInfo extends Position implements PositionUpdate {

+

+			/**

+			 * The offset to add to the {@link #line} and all following source

+			 * positions up to the next {@link PositionUpdate}.

+			 */

+			private final int _lineDelta;

+			

+			/**

+			 * The offset to add to the {@link #column} and all following

+			 * source positions up to the next {@link PositionUpdate}.

+			 */

+			private final int _columnDelta;

+

+			/** 

+			 * Creates a {@link PositionUpdate}.

+			 */

+			public DeltaInfo(int line, int column, int lineDelta,

+					int columnDelta) {

+				super(line, column);

+				_lineDelta = lineDelta;

+				_columnDelta = columnDelta;

+			}

+			

+			@Override

+			public int transformLine(int sourceLine) {

+				return sourceLine + _lineDelta;

+			}

+			

+			@Override

+			public int transformColumn(int sourceColumn) {

+				return sourceColumn + _columnDelta;

+			}

+			

+			@Override

+			public String toString() {

+				return "(" + line + ", " + column + ": " + _lineDelta + ", " + _columnDelta + ")";

+			}

+

+		}

+

+		/** 

+		 * Transforms the given {@link Position}.

+		 */

+		public Position transform(Position pos) {

+			return lookup(pos).transform(pos);

+		}

+

+		/** 

+		 * Transforms the given {@link Range}.

+		 */

+		public Range transform(Range range) {

+			Position begin = transform(range.begin);

+			Position end = transform(range.end);

+			if (begin == range.begin && end == range.end) {

+				// No change.

+				return range;

+			}

+			return new Range(begin, end);

+		}

+	}

+	

+	private static final class PositionMappingBuilder {

+		

+		private LineCounter _left;

+		

+		private LineCounter _right;

+		

+		private final PositionMapping _mapping = new PositionMapping();

+		

+		private int _lineDelta = 0;

+		private int _columnDelta = 0;

+		

+		/** 

+		 * Creates a {@link PositionMappingBuilder}.

+		 *

+		 * @param left The source {@link LineCounter}.

+		 * @param right The target {@link LineCounter}.

+		 */

+		public PositionMappingBuilder(LineCounter left, LineCounter right) {

+			_left = left;

+			_right = right;

+			update();

+		}

+		

+		/**

+		 * The built {@link PositionMapping}.

+		 */

+		public PositionMapping getMapping() {

+			return _mapping;

+		}

+		

+		public void update() {

+			int lineDelta = _right.getLine() - _left.getLine();

+			int columnDelta = _right.getColumn() - _left.getColumn();

+			

+			if (lineDelta != _lineDelta || columnDelta != _columnDelta) {

+				_mapping.add(_left.getLine(), _left.getColumn(), lineDelta, columnDelta);

+				

+				_lineDelta = lineDelta;

+				_columnDelta = columnDelta;

+			}

+		}

+		

+	}

+	

+	/**

+	 * Processor keeping track of the current line and column in a stream of

+	 * incoming characters.

+	 * 

+	 * @see #process(int)

+	 */

+	public static final class LineCounter {

+		

+		/**

+		 * Whether {@link #CR} has been seen on the input as last character.

+		 */

+		private boolean _crSeen;

+

+		private int _line = 1;

+

+		private int _column = 1;

+

+		/** 

+		 * Creates a {@link UnicodeEscapeProcessingProvider.LineCounter}.

+		 */

+		public LineCounter() {

+			super();

+		}

+		

+		/**

+		 * The line of the currently processed input character.

+		 */

+		public int getLine() {

+			return _line;

+		}

+		

+		/**

+		 * The column of the currently processed input character.

+		 */

+		public int getColumn() {

+			return _column;

+		}

+		

+		/** 

+		 * The current position.

+		 */

+		public Position getPosition() {

+			return new Position(getLine(), getColumn());

+		}

+

+		/** 

+		 * Analyzes the given character for line feed.

+		 */

+		public int process(int ch) {

+			switch (ch) {

+				case EOF: {

+					break;

+				}

+				case CR: {

+					incLine();

+					_crSeen = true;

+					break;

+				}

+				case LF: {

+					// CR LF does only count as a single line terminator.

+					if (_crSeen) {

+						_crSeen = false;

+					} else {

+						incLine();

+					}

+					break;

+				}

+				default: {

+					_crSeen = false;

+					_column++;

+				}

+			}

+			return ch;

+		}

+

+		private void incLine() {

+			_line++;

+			_column = 1;

+		}

+

+	}

+	

+}

diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/AccessSpecifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/AccessSpecifier.java
index 63e96b8..8319728 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/AccessSpecifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/AccessSpecifier.java
@@ -33,7 +33,7 @@
     PUBLIC("public"),
     PRIVATE("private"),
     PROTECTED("protected"),
-    DEFAULT("");
+    PACKAGE_PRIVATE("");
 
     private String codeRepresenation;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/ArrayCreationLevel.java b/javaparser-core/src/main/java/com/github/javaparser/ast/ArrayCreationLevel.java
index 09148fe..90ab946 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/ArrayCreationLevel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/ArrayCreationLevel.java
@@ -27,24 +27,22 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 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;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ArrayCreationLevelMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * In <code>new int[1][2];</code> there are two ArrayCreationLevel objects,
  * the first one contains the expression "1",
  * the second the expression "2".
  */
-public final class ArrayCreationLevel extends Node implements NodeWithAnnotations<ArrayCreationLevel> {
+public class ArrayCreationLevel extends Node implements NodeWithAnnotations<ArrayCreationLevel> {
 
     @OptionalProperty
     private Expression dimension;
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 fd8bb20..1493554 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
@@ -20,10 +20,7 @@
  */
 package com.github.javaparser.ast;
 
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParseStart;
-import com.github.javaparser.TokenRange;
+import com.github.javaparser.*;
 import com.github.javaparser.ast.body.AnnotationDeclaration;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.EnumDeclaration;
@@ -45,23 +42,26 @@
 import com.github.javaparser.utils.ClassUtils;
 import com.github.javaparser.utils.CodeGenerationUtils;
 import com.github.javaparser.utils.Utils;
-import javax.annotation.Generated;
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.EnumSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Function;
-import java.util.stream.Collectors;
-import static com.github.javaparser.JavaParser.parseName;
+import static com.github.javaparser.JavaToken.Kind.EOF;
 import static com.github.javaparser.Providers.UTF8;
 import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.Range.range;
+import static com.github.javaparser.StaticJavaParser.parseImport;
+import static com.github.javaparser.StaticJavaParser.parseName;
+import static com.github.javaparser.ast.Modifier.createModifierList;
 import static com.github.javaparser.utils.CodeGenerationUtils.subtractPaths;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <p>
@@ -78,7 +78,7 @@
  * @see TypeDeclaration
  * @see Storage
  */
-public final class CompilationUnit extends Node {
+public class CompilationUnit extends Node {
 
     @OptionalProperty
     private PackageDeclaration packageDeclaration;
@@ -222,8 +222,10 @@
         return this;
     }
 
-    public CompilationUnit addImport(ImportDeclaration imports) {
-        getImports().add(imports);
+    public CompilationUnit addImport(ImportDeclaration importDeclaration) {
+        if (getImports().stream().noneMatch(im -> im.toString().equals(importDeclaration.toString()))) {
+            getImports().add(importDeclaration);
+        }
         return this;
     }
 
@@ -309,12 +311,13 @@
      * @throws RuntimeException if clazz is an anonymous or local class
      */
     public CompilationUnit addImport(Class<?> clazz) {
-        if (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.getName().startsWith("java.lang"))
+        if (clazz.isArray()) {
+            return addImport(clazz.getComponentType());
+        }
+        if (ClassUtils.isPrimitiveOrWrapper(clazz) || "java.lang".equals(clazz.getPackage().getName()))
             return this;
         else if (clazz.isMemberClass())
             return addImport(clazz.getName().replace("$", "."));
-        else if (clazz.isArray() && !ClassUtils.isPrimitiveOrWrapper(clazz.getComponentType()) && !clazz.getComponentType().getName().startsWith("java.lang"))
-            return addImport(clazz.getComponentType().getName());
         else if (clazz.isAnonymousClass() || clazz.isLocalClass())
             throw new RuntimeException(clazz.getName() + " is an anonymous or local class therefore it can't be added with addImport");
         return addImport(clazz.getName());
@@ -339,13 +342,7 @@
             i.append(".*");
         }
         i.append(";");
-        ImportDeclaration importDeclaration = JavaParser.parseImport(i.toString());
-        if (getImports().stream().anyMatch(im -> im.toString().equals(importDeclaration.toString())))
-            return this;
-        else {
-            getImports().add(importDeclaration);
-            return this;
-        }
+        return addImport(parseImport(i.toString()));
     }
 
     /**
@@ -355,7 +352,7 @@
      * @return the newly created class
      */
     public ClassOrInterfaceDeclaration addClass(String name) {
-        return addClass(name, Modifier.PUBLIC);
+        return addClass(name, Modifier.Keyword.PUBLIC);
     }
 
     /**
@@ -365,8 +362,8 @@
      * @param modifiers the modifiers (like Modifier.PUBLIC)
      * @return the newly created class
      */
-    public ClassOrInterfaceDeclaration addClass(String name, Modifier... modifiers) {
-        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), false, name);
+    public ClassOrInterfaceDeclaration addClass(String name, Modifier.Keyword... modifiers) {
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(createModifierList(modifiers), false, name);
         getTypes().add(classOrInterfaceDeclaration);
         return classOrInterfaceDeclaration;
     }
@@ -378,7 +375,7 @@
      * @return the newly created class
      */
     public ClassOrInterfaceDeclaration addInterface(String name) {
-        return addInterface(name, Modifier.PUBLIC);
+        return addInterface(name, Modifier.Keyword.PUBLIC);
     }
 
     /**
@@ -388,8 +385,8 @@
      * @param modifiers the modifiers (like Modifier.PUBLIC)
      * @return the newly created class
      */
-    public ClassOrInterfaceDeclaration addInterface(String name, Modifier... modifiers) {
-        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), true, name);
+    public ClassOrInterfaceDeclaration addInterface(String name, Modifier.Keyword... modifiers) {
+        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration(createModifierList(modifiers), true, name);
         getTypes().add(classOrInterfaceDeclaration);
         return classOrInterfaceDeclaration;
     }
@@ -401,7 +398,7 @@
      * @return the newly created class
      */
     public EnumDeclaration addEnum(String name) {
-        return addEnum(name, Modifier.PUBLIC);
+        return addEnum(name, Modifier.Keyword.PUBLIC);
     }
 
     /**
@@ -411,8 +408,8 @@
      * @param modifiers the modifiers (like Modifier.PUBLIC)
      * @return the newly created class
      */
-    public EnumDeclaration addEnum(String name, Modifier... modifiers) {
-        EnumDeclaration enumDeclaration = new EnumDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name);
+    public EnumDeclaration addEnum(String name, Modifier.Keyword... modifiers) {
+        EnumDeclaration enumDeclaration = new EnumDeclaration(createModifierList(modifiers), name);
         getTypes().add(enumDeclaration);
         return enumDeclaration;
     }
@@ -424,7 +421,7 @@
      * @return the newly created class
      */
     public AnnotationDeclaration addAnnotationDeclaration(String name) {
-        return addAnnotationDeclaration(name, Modifier.PUBLIC);
+        return addAnnotationDeclaration(name, Modifier.Keyword.PUBLIC);
     }
 
     /**
@@ -434,8 +431,8 @@
      * @param modifiers the modifiers (like Modifier.PUBLIC)
      * @return the newly created class
      */
-    public AnnotationDeclaration addAnnotationDeclaration(String name, Modifier... modifiers) {
-        AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration(Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name);
+    public AnnotationDeclaration addAnnotationDeclaration(String name, Modifier.Keyword... modifiers) {
+        AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration(createModifierList(modifiers), name);
         getTypes().add(annotationDeclaration);
         return annotationDeclaration;
     }
@@ -568,6 +565,42 @@
         return this;
     }
 
+    public CompilationUnit setStorage(Path path, Charset charset) {
+        this.storage = new Storage(this, path, charset);
+        return this;
+    }
+
+    /**
+     * Create (or overwrite) a module declaration in this compilation unit with name "name".
+     *
+     * @return the module
+     */
+    public ModuleDeclaration setModule(String name) {
+        final ModuleDeclaration module = new ModuleDeclaration(parseName(name), false);
+        setModule(module);
+        return module;
+    }
+
+    /**
+     * Recalculates the ranges of all nodes by looking at the sizes of the tokens.
+     * This is useful when you have manually inserted or deleted tokens and still want to use the ranges.
+     */
+    public void recalculatePositions() {
+        if (!getTokenRange().isPresent()) {
+            throw new IllegalStateException("Can't recalculate positions without tokens.");
+        }
+        Position cursor = Position.HOME;
+        for (JavaToken t : getTokenRange().get()) {
+            int tokenLength = t.getKind() == EOF.getKind() ? 0 : t.getText().length() - 1;
+            t.setRange(range(cursor, cursor.right(tokenLength)));
+            if (t.getCategory().isEndOfLine()) {
+                cursor = cursor.nextLine();
+            } else {
+                cursor = cursor.right(tokenLength + 1);
+            }
+        }
+    }
+
     /**
      * Information about where this compilation unit was loaded from.
      * This class only stores the absolute location.
@@ -579,9 +612,18 @@
 
         private final Path path;
 
+        private final Charset encoding;
+
         private Storage(CompilationUnit compilationUnit, Path path) {
             this.compilationUnit = compilationUnit;
             this.path = path.toAbsolutePath();
+            this.encoding = UTF8;
+        }
+
+        private Storage(CompilationUnit compilationUnit, Path path, Charset encoding) {
+            this.compilationUnit = compilationUnit;
+            this.path = path.toAbsolutePath();
+            this.encoding = encoding;
         }
 
         /**
@@ -599,6 +641,13 @@
         }
 
         /**
+         * @return the encoding used to read the file.
+         */
+        public Charset getEncoding() {
+            return encoding;
+        }
+
+        /**
          * @return the source root directory, calculated from the path of this compiation unit, and the package
          * declaration of this compilation unit. If the package declaration is invalid (when it does not match the end
          * of the path) a RuntimeException is thrown.
@@ -624,16 +673,27 @@
         }
 
         /**
-         * Saves a compilation unit to its original location with formatting according to the function
-         * passed as a parameter.
+         * Saves a compilation unit to its original location with formatting according to the function passed as a
+         * parameter.
          *
          * @param makeOutput a function that formats the compilation unit
          */
         public void save(Function<CompilationUnit, String> makeOutput) {
+            save(makeOutput, encoding);
+        }
+
+        /**
+         * Saves a compilation unit to its original location with formatting and encoding according to the function and
+         * encoding passed as a parameter.
+         *
+         * @param makeOutput a function that formats the compilation unit
+         * @param encoding the encoding to use for the saved file
+         */
+        public void save(Function<CompilationUnit, String> makeOutput, Charset encoding) {
             try {
                 Files.createDirectories(path.getParent());
                 final String code = makeOutput.apply(getCompilationUnit());
-                Files.write(path, code.getBytes(UTF8));
+                Files.write(path, code.getBytes(encoding));
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/Generated.java b/javaparser-core/src/main/java/com/github/javaparser/ast/Generated.java
new file mode 100644
index 0000000..4c4df53
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/Generated.java
@@ -0,0 +1,25 @@
+package com.github.javaparser.ast;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Copied from javax.annotation.Generated and reduced a bit.
+ * <p>
+ * Indicates a part of the code that was generated,
+ * and will be overwritten the next time the generators are run.
+ */
+@Retention(SOURCE)
+@Target({PACKAGE, TYPE, ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD,
+        LOCAL_VARIABLE, PARAMETER})
+public @interface Generated {
+    /**
+     * The value element must have the name of the code generator.
+     * The recommended convention is to use the fully qualified name of the
+     * code generator. For example: <code>com.acme.generator.CodeGen</code>.
+     */
+    String[] value();
+}
\ No newline at end of file
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/ImportDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/ImportDeclaration.java
index 88ab096..98ae36a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/ImportDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/ImportDeclaration.java
@@ -20,21 +20,19 @@
  */
 package com.github.javaparser.ast;
 
-import com.github.javaparser.JavaParser;
 import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.expr.SimpleName;
 import com.github.javaparser.ast.nodeTypes.NodeWithName;
 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.JavaParser.*;
+import static com.github.javaparser.StaticJavaParser.parseName;
 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.ImportDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An import declaration.
@@ -47,7 +45,7 @@
  * <p>The name does not include the asterisk or the static keyword.</p>
  * @author Julio Vilmar Gesser
  */
-public final class ImportDeclaration extends Node implements NodeWithName<ImportDeclaration> {
+public class ImportDeclaration extends Node implements NodeWithName<ImportDeclaration> {
 
     private Name name;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java
index b6d0309..9cdc270 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/Modifier.java
@@ -1,72 +1,206 @@
-/*

- * 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;

-

-import java.util.EnumSet;

-

-/**

- * One of the modifiers known in Java.

- */

-public enum Modifier {

-    PUBLIC,

-    PROTECTED,

-    PRIVATE,

-    ABSTRACT,

-    STATIC,

-    FINAL,

-    TRANSIENT,

-    VOLATILE,

-    SYNCHRONIZED,

-    NATIVE,

-    STRICTFP,

-    TRANSITIVE,

-    DEFAULT;

-

-    final String codeRepresentation;

-

-    Modifier() {

-        this.codeRepresentation = name().toLowerCase();

-    }

-

-    /**

-     * @return the keyword represented by this modifier.

-     */

-    public String asString() {

-        return codeRepresentation;

-    }

-

-    public EnumSet<Modifier> toEnumSet() {

-        return EnumSet.of(this);

-    }

-

-    public static AccessSpecifier getAccessSpecifier(EnumSet<Modifier> modifiers) {

-        if (modifiers.contains(Modifier.PUBLIC)) {

-            return AccessSpecifier.PUBLIC;

-        } else if (modifiers.contains(Modifier.PROTECTED)) {

-            return AccessSpecifier.PROTECTED;

-        } else if (modifiers.contains(Modifier.PRIVATE)) {

-            return AccessSpecifier.PRIVATE;

-        } else {

-            return AccessSpecifier.DEFAULT;

-        }

-    }

-}

+/*
+ * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
+ * Copyright (C) 2011, 2013-2018 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;
+
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.observer.ObservableProperty;
+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.ModifierMetaModel;
+import java.util.Arrays;
+import static com.github.javaparser.ast.NodeList.toNodeList;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
+
+/**
+ * A modifier, like private, public, or volatile.
+ */
+public class Modifier extends Node {
+
+    public static Modifier publicModifier() {
+        return new Modifier(Keyword.PUBLIC);
+    }
+
+    public static Modifier protectedModifier() {
+        return new Modifier(Keyword.PROTECTED);
+    }
+
+    public static Modifier privateModifier() {
+        return new Modifier(Keyword.PRIVATE);
+    }
+
+    public static Modifier abstractModifier() {
+        return new Modifier(Keyword.ABSTRACT);
+    }
+
+    public static Modifier staticModifier() {
+        return new Modifier(Keyword.STATIC);
+    }
+
+    public static Modifier finalModifier() {
+        return new Modifier(Keyword.FINAL);
+    }
+
+    public static Modifier transientModifier() {
+        return new Modifier(Keyword.TRANSIENT);
+    }
+
+    public static Modifier volatileModifier() {
+        return new Modifier(Keyword.VOLATILE);
+    }
+
+    public static Modifier synchronizedModifier() {
+        return new Modifier(Keyword.SYNCHRONIZED);
+    }
+
+    public static Modifier nativeModifier() {
+        return new Modifier(Keyword.NATIVE);
+    }
+
+    public static Modifier strictfpModifier() {
+        return new Modifier(Keyword.STRICTFP);
+    }
+
+    public static Modifier transitiveModifier() {
+        return new Modifier(Keyword.TRANSITIVE);
+    }
+
+    /**
+     * The Java modifier keywords.
+     */
+    public enum Keyword {
+
+        DEFAULT("default"),
+        PUBLIC("public"),
+        PROTECTED("protected"),
+        PRIVATE("private"),
+        ABSTRACT("abstract"),
+        STATIC("static"),
+        FINAL("final"),
+        TRANSIENT("transient"),
+        VOLATILE("volatile"),
+        SYNCHRONIZED("synchronized"),
+        NATIVE("native"),
+        STRICTFP("strictfp"),
+        TRANSITIVE("transitive");
+
+        private final String codeRepresentation;
+
+        Keyword(String codeRepresentation) {
+            this.codeRepresentation = codeRepresentation;
+        }
+
+        /**
+         * @return the Java keyword represented by this enum constant.
+         */
+        public String asString() {
+            return codeRepresentation;
+        }
+    }
+
+    private Keyword keyword;
+
+    public Modifier() {
+        this(Keyword.PUBLIC);
+    }
+
+    @AllFieldsConstructor
+    public Modifier(Keyword keyword) {
+        this(null, keyword);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public Modifier(TokenRange tokenRange, Keyword keyword) {
+        super(tokenRange);
+        setKeyword(keyword);
+        customInitialization();
+    }
+
+    @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);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Keyword getKeyword() {
+        return keyword;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Modifier setKeyword(final Keyword keyword) {
+        assertNotNull(keyword);
+        if (keyword == this.keyword) {
+            return (Modifier) this;
+        }
+        notifyPropertyChange(ObservableProperty.KEYWORD, this.keyword, keyword);
+        this.keyword = keyword;
+        return this;
+    }
+
+    /**
+     * Utility method that instantiaties "Modifier"s for the keywords,
+     * and puts them in a NodeList.
+     */
+    public static NodeList<Modifier> createModifierList(Modifier.Keyword... modifiers) {
+        return Arrays.stream(modifiers).map(Modifier::new).collect(toNodeList());
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        return super.remove(node);
+    }
+
+    @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
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public Modifier clone() {
+        return (Modifier) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ModifierMetaModel getMetaModel() {
+        return JavaParserMetaModel.modifierMetaModel;
+    }
+}
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 98d0bbc..8d3d080 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
@@ -39,21 +39,21 @@
 import com.github.javaparser.printer.PrettyPrinter;
 import com.github.javaparser.printer.PrettyPrinterConfiguration;
 import com.github.javaparser.resolution.SymbolResolver;
-import javax.annotation.Generated;
+import com.github.javaparser.resolution.types.ResolvedType;
+
 import java.util.*;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
+
 import static com.github.javaparser.ast.Node.Parsedness.PARSED;
 import static com.github.javaparser.ast.Node.TreeTraversal.PREORDER;
+import static java.util.Collections.emptySet;
 import static java.util.Collections.unmodifiableList;
 import static java.util.Spliterator.DISTINCT;
 import static java.util.Spliterator.NONNULL;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.metamodel.NodeMetaModel;
-import com.github.javaparser.metamodel.JavaParserMetaModel;
 
 /**
  * Base class for all nodes of the abstract syntax tree.
@@ -143,7 +143,7 @@
         return 0;
     };
 
-    private static final PrettyPrinter toStringPrinter = new PrettyPrinter(new PrettyPrinterConfiguration());
+    private static PrettyPrinterConfiguration toStringPrettyPrinterConfiguration = new PrettyPrinterConfiguration();
 
     protected static final PrettyPrinterConfiguration prettyPrinterNoCommentsConfiguration = new PrettyPrinterConfiguration().setPrintComments(false);
 
@@ -222,7 +222,7 @@
 
     /**
      * @param range the range of characters in the source code that this node covers. null can be used to indicate that
-     * no range information is known, or that it is not of interest.
+     *              no range information is known, or that it is not of interest.
      */
     public Node setRange(Range range) {
         if (this.range == range) {
@@ -238,13 +238,10 @@
      *
      * @param comment to be set
      */
-    public final Node setComment(final Comment comment) {
+    public Node setComment(final Comment comment) {
         if (this.comment == comment) {
             return this;
         }
-        if (comment != null && (this instanceof Comment)) {
-            throw new RuntimeException("A comment can not be commented");
-        }
         notifyPropertyChange(ObservableProperty.COMMENT, this.comment, comment);
         if (this.comment != null) {
             this.comment.setCommentedNode(null);
@@ -275,15 +272,18 @@
     }
 
     /**
-     * Return the String representation of this node.
-     *
-     * @return the String representation of this node
+     * @return pretty printed source code for this node and its children.
+     * Formatting can be configured with Node.setToStringPrettyPrinterConfiguration.
      */
     @Override
     public final String toString() {
-        return toStringPrinter.print(this);
+        return new PrettyPrinter(toStringPrettyPrinterConfiguration).print(this);
     }
 
+    /**
+     * @return pretty printed source code for this node and its children.
+     * Formatting can be configured with parameter prettyPrinterConfiguration.
+     */
     public final String toString(PrettyPrinterConfiguration prettyPrinterConfiguration) {
         return new PrettyPrinter(prettyPrinterConfiguration).print(this);
     }
@@ -324,6 +324,7 @@
     public boolean removeOrphanComment(Comment comment) {
         boolean removed = orphanComments.remove(comment);
         if (removed) {
+            notifyPropertyChange(ObservableProperty.COMMENT, comment, null);
             comment.setParentNode(null);
         }
         return removed;
@@ -403,24 +404,17 @@
 
     public static final int ABSOLUTE_END_LINE = -2;
 
-    /**
-     * @deprecated use getComment().isPresent()
-     */
-    @Deprecated
-    public boolean hasComment() {
-        return comment != null;
-    }
-
     public void tryAddImportToParentCompilationUnit(Class<?> clazz) {
-        getAncestorOfType(CompilationUnit.class).ifPresent(p -> p.addImport(clazz));
+        findAncestor(CompilationUnit.class).ifPresent(p -> p.addImport(clazz));
     }
 
     /**
      * Recursively finds all nodes of a certain type.
      *
      * @param clazz the type of node to find.
-     * @deprecated use find(Class)
+     * @deprecated use {@link Node#findAll(Class)} but be aware that findAll also considers the initial node.
      */
+    @Deprecated
     public <N extends Node> List<N> getChildNodesByType(Class<N> clazz) {
         List<N> nodes = new ArrayList<>();
         for (Node child : getChildNodes()) {
@@ -433,7 +427,7 @@
     }
 
     /**
-     * @deprecated use findAll(Class)
+     * @deprecated use {@link Node#findAll(Class)} but be aware that findAll also considers the initial node.
      */
     @Deprecated
     public <N extends Node> List<N> getNodesByType(Class<N> clazz) {
@@ -445,23 +439,41 @@
      *
      * @param <M> The type of the data.
      * @param key The key for the data
-     * @return The data or null of no data was found for the given key
+     * @return The data.
+     * @throws IllegalStateException if the key was not set in this node.
+     * @see Node#containsData(DataKey)
      * @see DataKey
      */
     @SuppressWarnings("unchecked")
     public <M> M getData(final DataKey<M> key) {
         if (data == null) {
-            return null;
+            throw new IllegalStateException("No data of this type found. Use containsData to check for this first.");
         }
-        return (M) data.get(key);
+        M value = (M) data.get(key);
+        if (value == null) {
+            throw new IllegalStateException("No data of this type found. Use containsData to check for this first.");
+        }
+        return value;
+    }
+
+    /**
+     * This method was added to support the clone method.
+     *
+     * @return all known data keys.
+     */
+    public Set<DataKey<?>> getDataKeys() {
+        if (data == null) {
+            return emptySet();
+        }
+        return data.keySet();
     }
 
     /**
      * Sets data for this node using the given key.
      * For information on creating DataKey, see {@link DataKey}.
      *
-     * @param <M> The type of data
-     * @param key The singleton key for the data
+     * @param <M>    The type of data
+     * @param key    The singleton key for the data
      * @param object The data object
      * @see DataKey
      */
@@ -474,12 +486,24 @@
 
     /**
      * @return does this node have data for this key?
+     * @see DataKey
      */
     public boolean containsData(DataKey<?> key) {
         if (data == null) {
             return false;
         }
-        return data.get(key) != null;
+        return data.containsKey(key);
+    }
+
+    /**
+     * Remove data by key.
+     *
+     * @see DataKey
+     */
+    public void removeData(DataKey<ResolvedType> key) {
+        if (data != null) {
+            data.remove(key);
+        }
     }
 
     /**
@@ -557,7 +581,7 @@
         if (mode == null) {
             throw new IllegalArgumentException("Mode should be not null");
         }
-        switch(mode) {
+        switch (mode) {
             case JUST_THIS_NODE:
                 register(observer);
                 break;
@@ -640,6 +664,14 @@
         return this;
     }
 
+    public static PrettyPrinterConfiguration getToStringPrettyPrinterConfiguration() {
+        return toStringPrettyPrinterConfiguration;
+    }
+
+    public static void setToStringPrettyPrinterConfiguration(PrettyPrinterConfiguration toStringPrettyPrinterConfiguration) {
+        Node.toStringPrettyPrinterConfiguration = toStringPrettyPrinterConfiguration;
+    }
+
     @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
     public boolean replace(Node node, Node replacementNode) {
         if (node == null)
@@ -695,7 +727,7 @@
     }
 
     private Iterator<Node> treeIterator(TreeTraversal traversal) {
-        switch(traversal) {
+        switch (traversal) {
             case BREADTHFIRST:
                 return new BreadthFirstIterator(this);
             case POSTORDER:
@@ -823,17 +855,14 @@
     }
 
     /**
-     * Walks the parents of this node, returning the first node of type "nodeType" or empty() if none is found.
+     * Determines whether this node is an ancestor of the given node. A node is <i>not</i> an ancestor of itself.
+     *
+     * @param descendant the node for which to determine whether it has this node as an ancestor.
+     * @return {@code true} if this node is an ancestor of the given node, and {@code false} otherwise.
+     * @see HasParentNode#isDescendantOf(Node)
      */
-    public <N extends Node> Optional<N> findParent(Class<N> nodeType) {
-        Node n = this;
-        while (n.getParentNode().isPresent()) {
-            n = n.getParentNode().get();
-            if (nodeType.isAssignableFrom(n.getClass())) {
-                return Optional.of(nodeType.cast(n));
-            }
-        }
-        return Optional.empty();
+    public boolean isAncestorOf(Node descendant) {
+        return this != descendant && findFirst(Node.class, n -> n == descendant).isPresent();
     }
 
     /**
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java b/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java
index f370e96..e10e0b4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/NodeList.java
@@ -60,6 +60,7 @@
         this.addAll(n);
     }
 
+    @SafeVarargs
     public NodeList(N... n) {
         this.addAll(Arrays.asList(n));
     }
@@ -480,7 +481,9 @@
 
     @Override
     public void register(AstObserver observer) {
-        this.observers.add(observer);
+        if(!this.observers.contains(observer)) {
+            this.observers.add(observer);
+        }
     }
 
     @Override
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/PackageDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/PackageDeclaration.java
index 65a1ca7..084e1f7 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/PackageDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/PackageDeclaration.java
@@ -27,15 +27,13 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 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.PackageDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A package declaration.
@@ -44,7 +42,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class PackageDeclaration extends Node implements NodeWithAnnotations<PackageDeclaration>, NodeWithName<PackageDeclaration> {
+public class PackageDeclaration extends Node implements NodeWithAnnotations<PackageDeclaration>, NodeWithName<PackageDeclaration> {
 
     private NodeList<AnnotationExpr> annotations = new NodeList<>();
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationDeclaration.java
index aa793ef..c3903b0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationDeclaration.java
@@ -27,39 +27,36 @@
 import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.expr.SimpleName;
 import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithAbstractModifier;
+import com.github.javaparser.ast.type.Type;
 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.AnnotationDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.List;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
 import com.github.javaparser.resolution.declarations.ResolvedAnnotationDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An annotation type declaration.<br/><code>@interface X { ... }</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class AnnotationDeclaration extends TypeDeclaration<AnnotationDeclaration> implements NodeWithAbstractModifier<AnnotationDeclaration>, Resolvable<ResolvedAnnotationDeclaration> {
+public class AnnotationDeclaration extends TypeDeclaration<AnnotationDeclaration> implements NodeWithAbstractModifier<AnnotationDeclaration>, Resolvable<ResolvedAnnotationDeclaration> {
 
     public AnnotationDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new SimpleName(), new NodeList<>());
+        this(null, new NodeList<>(), new NodeList<>(), new SimpleName(), new NodeList<>());
     }
 
-    public AnnotationDeclaration(EnumSet<Modifier> modifiers, String name) {
+    public AnnotationDeclaration(NodeList<Modifier> modifiers, String name) {
         this(null, modifiers, new NodeList<>(), new SimpleName(name), new NodeList<>());
     }
 
     @AllFieldsConstructor
-    public AnnotationDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
+    public AnnotationDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
         this(null, modifiers, annotations, name, members);
     }
 
@@ -67,7 +64,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public AnnotationDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
+    public AnnotationDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
         super(tokenRange, modifiers, annotations, name, members);
         customInitialization();
     }
@@ -139,4 +136,9 @@
     public Optional<AnnotationDeclaration> toAnnotationDeclaration() {
         return Optional.of(this);
     }
+
+    @Override
+    public FieldDeclaration addField(Type type, String name, Modifier.Keyword... modifiers) {
+        throw new IllegalStateException("Cannot add a field to an annotation declaration.");
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationMemberDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationMemberDeclaration.java
index 48b6db6..8a97013 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationMemberDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/AnnotationMemberDeclaration.java
@@ -44,12 +44,10 @@
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.resolution.Resolvable;
 import com.github.javaparser.resolution.declarations.ResolvedAnnotationMemberDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
-import javax.annotation.Generated;
-import java.util.EnumSet;
 import java.util.Optional;
 import java.util.function.Consumer;
 import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The "int id();" in <code>@interface X { int id(); }</code>
@@ -59,9 +57,9 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class AnnotationMemberDeclaration extends BodyDeclaration<AnnotationMemberDeclaration> implements NodeWithJavadoc<AnnotationMemberDeclaration>, NodeWithSimpleName<AnnotationMemberDeclaration>, NodeWithType<AnnotationMemberDeclaration, Type>, NodeWithPublicModifier<AnnotationMemberDeclaration>, NodeWithAbstractModifier<AnnotationMemberDeclaration>, Resolvable<ResolvedAnnotationMemberDeclaration> {
+public class AnnotationMemberDeclaration extends BodyDeclaration<AnnotationMemberDeclaration> implements NodeWithJavadoc<AnnotationMemberDeclaration>, NodeWithSimpleName<AnnotationMemberDeclaration>, NodeWithType<AnnotationMemberDeclaration, Type>, NodeWithPublicModifier<AnnotationMemberDeclaration>, NodeWithAbstractModifier<AnnotationMemberDeclaration>, Resolvable<ResolvedAnnotationMemberDeclaration> {
 
-    private EnumSet<Modifier> modifiers;
+    private NodeList<Modifier> modifiers;
 
     private Type type;
 
@@ -71,15 +69,15 @@
     private Expression defaultValue;
 
     public AnnotationMemberDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new ClassOrInterfaceType(), new SimpleName(), null);
+        this(null, new NodeList<>(), new NodeList<>(), new ClassOrInterfaceType(), new SimpleName(), null);
     }
 
-    public AnnotationMemberDeclaration(EnumSet<Modifier> modifiers, Type type, String name, Expression defaultValue) {
+    public AnnotationMemberDeclaration(NodeList<Modifier> modifiers, Type type, String name, Expression defaultValue) {
         this(null, modifiers, new NodeList<>(), type, new SimpleName(name), defaultValue);
     }
 
     @AllFieldsConstructor
-    public AnnotationMemberDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, SimpleName name, Expression defaultValue) {
+    public AnnotationMemberDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, SimpleName name, Expression defaultValue) {
         this(null, modifiers, annotations, type, name, defaultValue);
     }
 
@@ -87,7 +85,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public AnnotationMemberDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, SimpleName name, Expression defaultValue) {
+    public AnnotationMemberDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, SimpleName name, Expression defaultValue) {
         super(tokenRange, annotations);
         setModifiers(modifiers);
         setType(type);
@@ -120,7 +118,7 @@
      * @see Modifier
      */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public EnumSet<Modifier> getModifiers() {
+    public NodeList<Modifier> getModifiers() {
         return modifiers;
     }
 
@@ -159,13 +157,16 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public AnnotationMemberDeclaration setModifiers(final EnumSet<Modifier> modifiers) {
+    public AnnotationMemberDeclaration setModifiers(final NodeList<Modifier> modifiers) {
         assertNotNull(modifiers);
         if (modifiers == this.modifiers) {
             return (AnnotationMemberDeclaration) this;
         }
         notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
+        if (this.modifiers != null)
+            this.modifiers.setParentNode(null);
         this.modifiers = modifiers;
+        setAsParentNodeOf(modifiers);
         return this;
     }
 
@@ -208,6 +209,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.remove(i);
+                return true;
+            }
+        }
         return super.remove(node);
     }
 
@@ -234,6 +241,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.set(i, (Modifier) replacementNode);
+                return true;
+            }
+        }
         if (node == name) {
             setName((SimpleName) replacementNode);
             return true;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/BodyDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/BodyDeclaration.java
index dc871e3..b762518 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/BodyDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/BodyDeclaration.java
@@ -30,8 +30,8 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.BodyDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import java.util.Optional;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/CallableDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/CallableDeclaration.java
index e2e41fe..09c2330 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/CallableDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/CallableDeclaration.java
@@ -38,8 +38,7 @@
 import com.github.javaparser.metamodel.CallableDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.OptionalProperty;
-import javax.annotation.Generated;
-import java.util.EnumSet;
+import com.github.javaparser.ast.Generated;
 import java.util.List;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import static java.util.stream.Collectors.joining;
@@ -52,7 +51,7 @@
  */
 public abstract class CallableDeclaration<T extends CallableDeclaration<?>> extends BodyDeclaration<T> implements NodeWithAccessModifiers<T>, NodeWithDeclaration, NodeWithSimpleName<T>, NodeWithParameters<T>, NodeWithThrownExceptions<T>, NodeWithTypeParameters<T>, NodeWithJavadoc<T>, NodeWithAbstractModifier<T>, NodeWithStaticModifier<T>, NodeWithFinalModifier<T>, NodeWithStrictfpModifier<T> {
 
-    private EnumSet<Modifier> modifiers;
+    private NodeList<Modifier> modifiers;
 
     private NodeList<TypeParameter> typeParameters;
 
@@ -66,7 +65,7 @@
     private ReceiverParameter receiverParameter;
 
     @AllFieldsConstructor
-    CallableDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter) {
+    CallableDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter) {
         this(null, modifiers, annotations, typeParameters, name, parameters, thrownExceptions, receiverParameter);
     }
 
@@ -74,7 +73,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public CallableDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter) {
+    public CallableDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter) {
         super(tokenRange, annotations);
         setModifiers(modifiers);
         setTypeParameters(typeParameters);
@@ -92,19 +91,22 @@
      * @see Modifier
      */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public EnumSet<Modifier> getModifiers() {
+    public NodeList<Modifier> getModifiers() {
         return modifiers;
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
     @SuppressWarnings("unchecked")
-    public T setModifiers(final EnumSet<Modifier> modifiers) {
+    public T setModifiers(final NodeList<Modifier> modifiers) {
         assertNotNull(modifiers);
         if (modifiers == this.modifiers) {
             return (T) this;
         }
         notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
+        if (this.modifiers != null)
+            this.modifiers.setParentNode(null);
         this.modifiers = modifiers;
+        setAsParentNodeOf(modifiers);
         return (T) this;
     }
 
@@ -188,16 +190,6 @@
         return (T) this;
     }
 
-    public String getDeclarationAsString(boolean includingModifiers, boolean includingThrows) {
-        return getDeclarationAsString(includingModifiers, includingThrows, true);
-    }
-
-    public String getDeclarationAsString() {
-        return getDeclarationAsString(true, true, true);
-    }
-
-    public abstract String getDeclarationAsString(boolean includingModifiers, boolean includingThrows, boolean includingParameterName);
-
     protected String appendThrowsIfRequested(boolean includingThrows) {
         StringBuilder sb = new StringBuilder();
         if (includingThrows) {
@@ -220,6 +212,12 @@
     public boolean remove(Node node) {
         if (node == null)
             return false;
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.remove(i);
+                return true;
+            }
+        }
         for (int i = 0; i < parameters.size(); i++) {
             if (parameters.get(i) == node) {
                 parameters.remove(i);
@@ -348,6 +346,12 @@
     public boolean replace(Node node, Node replacementNode) {
         if (node == null)
             return false;
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.set(i, (Modifier) replacementNode);
+                return true;
+            }
+        }
         if (node == name) {
             setName((SimpleName) replacementNode);
             return true;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclaration.java
index a275066..81eb6a0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclaration.java
@@ -43,20 +43,18 @@
 import com.github.javaparser.metamodel.ClassOrInterfaceDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.resolution.Resolvable;
-import com.github.javaparser.resolution.declarations.ResolvedAnnotationDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import javax.annotation.Generated;
-import java.util.EnumSet;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A definition of a class or interface.<br/><code>class X { ... }</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class ClassOrInterfaceDeclaration extends TypeDeclaration<ClassOrInterfaceDeclaration> implements NodeWithImplements<ClassOrInterfaceDeclaration>, NodeWithExtends<ClassOrInterfaceDeclaration>, NodeWithTypeParameters<ClassOrInterfaceDeclaration>, NodeWithAbstractModifier<ClassOrInterfaceDeclaration>, NodeWithFinalModifier<ClassOrInterfaceDeclaration>, NodeWithConstructors<ClassOrInterfaceDeclaration>, Resolvable<ResolvedReferenceTypeDeclaration> {
+public class ClassOrInterfaceDeclaration extends TypeDeclaration<ClassOrInterfaceDeclaration> implements NodeWithImplements<ClassOrInterfaceDeclaration>, NodeWithExtends<ClassOrInterfaceDeclaration>, NodeWithTypeParameters<ClassOrInterfaceDeclaration>, NodeWithAbstractModifier<ClassOrInterfaceDeclaration>, NodeWithFinalModifier<ClassOrInterfaceDeclaration>, NodeWithConstructors<ClassOrInterfaceDeclaration>, Resolvable<ResolvedReferenceTypeDeclaration> {
 
     private boolean isInterface;
 
@@ -68,15 +66,15 @@
     private NodeList<ClassOrInterfaceType> implementedTypes;
 
     public ClassOrInterfaceDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), false, new SimpleName(), new NodeList<>(), new NodeList<>(), new NodeList<>(), new NodeList<>());
+        this(null, new NodeList<>(), new NodeList<>(), false, new SimpleName(), new NodeList<>(), new NodeList<>(), new NodeList<>(), new NodeList<>());
     }
 
-    public ClassOrInterfaceDeclaration(final EnumSet<Modifier> modifiers, final boolean isInterface, final String name) {
+    public ClassOrInterfaceDeclaration(final NodeList<Modifier> modifiers, final boolean isInterface, final String name) {
         this(null, modifiers, new NodeList<>(), isInterface, new SimpleName(name), new NodeList<>(), new NodeList<>(), new NodeList<>(), new NodeList<>());
     }
 
     @AllFieldsConstructor
-    public ClassOrInterfaceDeclaration(final EnumSet<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final boolean isInterface, final SimpleName name, final NodeList<TypeParameter> typeParameters, final NodeList<ClassOrInterfaceType> extendedTypes, final NodeList<ClassOrInterfaceType> implementedTypes, final NodeList<BodyDeclaration<?>> members) {
+    public ClassOrInterfaceDeclaration(final NodeList<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final boolean isInterface, final SimpleName name, final NodeList<TypeParameter> typeParameters, final NodeList<ClassOrInterfaceType> extendedTypes, final NodeList<ClassOrInterfaceType> implementedTypes, final NodeList<BodyDeclaration<?>> members) {
         this(null, modifiers, annotations, isInterface, name, typeParameters, extendedTypes, implementedTypes, members);
     }
 
@@ -84,7 +82,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ClassOrInterfaceDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, boolean isInterface, SimpleName name, NodeList<TypeParameter> typeParameters, NodeList<ClassOrInterfaceType> extendedTypes, NodeList<ClassOrInterfaceType> implementedTypes, NodeList<BodyDeclaration<?>> members) {
+    public ClassOrInterfaceDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, boolean isInterface, SimpleName name, NodeList<TypeParameter> typeParameters, NodeList<ClassOrInterfaceType> extendedTypes, NodeList<ClassOrInterfaceType> implementedTypes, NodeList<BodyDeclaration<?>> members) {
         super(tokenRange, modifiers, annotations, name, members);
         setInterface(isInterface);
         setTypeParameters(typeParameters);
@@ -210,6 +208,14 @@
         return getParentNode().map(p -> p instanceof LocalClassDeclarationStmt).orElse(false);
     }
 
+    @Override
+    public Optional<String> getFullyQualifiedName() {
+        if (isLocalClassDeclaration()) {
+            return Optional.empty();
+        }
+        return super.getFullyQualifiedName();
+    }
+
     /**
      * @return is this an inner class?
      * NOTE: many people are confused over terminology. Refer to https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html .
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/ConstructorDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/ConstructorDeclaration.java
index ab1dad9..40ff79a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/ConstructorDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/ConstructorDeclaration.java
@@ -20,10 +20,7 @@
  */
 package com.github.javaparser.ast.body;
 
-import com.github.javaparser.ast.AccessSpecifier;
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.expr.SimpleName;
 import com.github.javaparser.ast.nodeTypes.*;
@@ -32,51 +29,50 @@
 import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.ast.type.ReferenceType;
 import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.EnumSet;
-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.ConstructorDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
 import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
-import java.util.function.Consumer;
 import java.util.Optional;
+import java.util.function.Consumer;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A constructor declaration: <code>class X { X() { } }</code> where X(){} is the constructor declaration.
- *
+ * <p>
  * <br/>All annotations preceding the name will be set on this object, not on the class.
  * JavaParser doesn't know if it they are applicable to the method or the class.
  *
  * @author Julio Vilmar Gesser
  */
-public final class ConstructorDeclaration extends CallableDeclaration<ConstructorDeclaration> implements NodeWithBlockStmt<ConstructorDeclaration>, NodeWithAccessModifiers<ConstructorDeclaration>, NodeWithJavadoc<ConstructorDeclaration>, NodeWithSimpleName<ConstructorDeclaration>, NodeWithParameters<ConstructorDeclaration>, NodeWithThrownExceptions<ConstructorDeclaration>, NodeWithTypeParameters<ConstructorDeclaration>, Resolvable<ResolvedConstructorDeclaration> {
+public class ConstructorDeclaration extends CallableDeclaration<ConstructorDeclaration> implements NodeWithBlockStmt<ConstructorDeclaration>, NodeWithAccessModifiers<ConstructorDeclaration>, NodeWithJavadoc<ConstructorDeclaration>, NodeWithSimpleName<ConstructorDeclaration>, NodeWithParameters<ConstructorDeclaration>, NodeWithThrownExceptions<ConstructorDeclaration>, NodeWithTypeParameters<ConstructorDeclaration>, Resolvable<ResolvedConstructorDeclaration> {
 
     private BlockStmt body;
 
     public ConstructorDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new NodeList<>(), new SimpleName(), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
+        this(null, new NodeList<>(), new NodeList<>(), new NodeList<>(), new SimpleName(), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
     }
 
     public ConstructorDeclaration(String name) {
-        this(null, EnumSet.of(Modifier.PUBLIC), new NodeList<>(), new NodeList<>(), new SimpleName(name), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
+        this(null, new NodeList<>(new Modifier()), new NodeList<>(), new NodeList<>(), new SimpleName(name), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
     }
 
-    public ConstructorDeclaration(EnumSet<Modifier> modifiers, String name) {
+    public ConstructorDeclaration(NodeList<Modifier> modifiers, String name) {
         this(null, modifiers, new NodeList<>(), new NodeList<>(), new SimpleName(name), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
     }
 
-    public ConstructorDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body) {
+    public ConstructorDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body) {
         this(null, modifiers, annotations, typeParameters, name, parameters, thrownExceptions, body, null);
     }
 
     @AllFieldsConstructor
-    public ConstructorDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body, ReceiverParameter receiverParameter) {
+    public ConstructorDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body, ReceiverParameter receiverParameter) {
         this(null, modifiers, annotations, typeParameters, name, parameters, thrownExceptions, body, receiverParameter);
     }
 
@@ -84,7 +80,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ConstructorDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body, ReceiverParameter receiverParameter) {
+    public ConstructorDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body, ReceiverParameter receiverParameter) {
         super(tokenRange, modifiers, annotations, typeParameters, name, parameters, thrownExceptions, receiverParameter);
         setBody(body);
         customInitialization();
@@ -128,7 +124,7 @@
     }
 
     @Override
-    public ConstructorDeclaration setModifiers(final EnumSet<Modifier> modifiers) {
+    public ConstructorDeclaration setModifiers(final NodeList<Modifier> modifiers) {
         return super.setModifiers(modifiers);
     }
 
@@ -162,9 +158,8 @@
     public String getDeclarationAsString(boolean includingModifiers, boolean includingThrows, boolean includingParameterName) {
         StringBuilder sb = new StringBuilder();
         if (includingModifiers) {
-            AccessSpecifier accessSpecifier = Modifier.getAccessSpecifier(getModifiers());
-            sb.append(accessSpecifier.asString());
-            sb.append(accessSpecifier == AccessSpecifier.DEFAULT ? "" : " ");
+            AccessSpecifier accessSpecifier = getAccessSpecifier();
+            sb.append(accessSpecifier.asString()).append(" ");
         }
         sb.append(getName());
         sb.append("(");
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumConstantDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumConstantDeclaration.java
index 5a331e4..3cafe32 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumConstantDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumConstantDeclaration.java
@@ -31,27 +31,24 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 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.EnumConstantDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
-import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedEnumConstantDeclaration;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * One of the values an enum can take. A(1) and B(2) in this example: <code>enum X { A(1), B(2) }</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class EnumConstantDeclaration extends BodyDeclaration<EnumConstantDeclaration> implements NodeWithJavadoc<EnumConstantDeclaration>, NodeWithSimpleName<EnumConstantDeclaration>, NodeWithArguments<EnumConstantDeclaration>, Resolvable<ResolvedEnumConstantDeclaration> {
+public class EnumConstantDeclaration extends BodyDeclaration<EnumConstantDeclaration> implements NodeWithJavadoc<EnumConstantDeclaration>, NodeWithSimpleName<EnumConstantDeclaration>, NodeWithArguments<EnumConstantDeclaration>, Resolvable<ResolvedEnumConstantDeclaration> {
 
     private SimpleName name;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumDeclaration.java
index 44fb1e4..05d8896 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/EnumDeclaration.java
@@ -38,34 +38,33 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.resolution.Resolvable;
 import com.github.javaparser.resolution.declarations.ResolvedEnumDeclaration;
-import javax.annotation.Generated;
-import java.util.EnumSet;
 import static com.github.javaparser.utils.Utils.assertNonEmpty;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The declaration of an enum.<br/><code>enum X { ... }</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class EnumDeclaration extends TypeDeclaration<EnumDeclaration> implements NodeWithImplements<EnumDeclaration>, NodeWithConstructors<EnumDeclaration>, Resolvable<ResolvedEnumDeclaration> {
+public class EnumDeclaration extends TypeDeclaration<EnumDeclaration> implements NodeWithImplements<EnumDeclaration>, NodeWithConstructors<EnumDeclaration>, Resolvable<ResolvedEnumDeclaration> {
 
     private NodeList<ClassOrInterfaceType> implementedTypes;
 
     private NodeList<EnumConstantDeclaration> entries;
 
     public EnumDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new SimpleName(), new NodeList<>(), new NodeList<>(), new NodeList<>());
+        this(null, new NodeList<>(), new NodeList<>(), new SimpleName(), new NodeList<>(), new NodeList<>(), new NodeList<>());
     }
 
-    public EnumDeclaration(EnumSet<Modifier> modifiers, String name) {
+    public EnumDeclaration(NodeList<Modifier> modifiers, String name) {
         this(null, modifiers, new NodeList<>(), new SimpleName(name), new NodeList<>(), new NodeList<>(), new NodeList<>());
     }
 
     @AllFieldsConstructor
-    public EnumDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<ClassOrInterfaceType> implementedTypes, NodeList<EnumConstantDeclaration> entries, NodeList<BodyDeclaration<?>> members) {
+    public EnumDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<ClassOrInterfaceType> implementedTypes, NodeList<EnumConstantDeclaration> entries, NodeList<BodyDeclaration<?>> members) {
         this(null, modifiers, annotations, name, implementedTypes, entries, members);
     }
 
@@ -73,7 +72,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public EnumDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<ClassOrInterfaceType> implementedTypes, NodeList<EnumConstantDeclaration> entries, NodeList<BodyDeclaration<?>> members) {
+    public EnumDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<ClassOrInterfaceType> implementedTypes, NodeList<EnumConstantDeclaration> entries, NodeList<BodyDeclaration<?>> members) {
         super(tokenRange, modifiers, annotations, name, members);
         setImplementedTypes(implementedTypes);
         setEntries(entries);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java
index 547e95a..9178025 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/FieldDeclaration.java
@@ -20,10 +20,8 @@
  */
 package com.github.javaparser.ast.body;
 
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.expr.AssignExpr;
 import com.github.javaparser.ast.expr.AssignExpr.Operator;
@@ -44,19 +42,14 @@
 import com.github.javaparser.metamodel.FieldDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.NonEmptyProperty;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.List;
+import com.github.javaparser.resolution.Resolvable;
+import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
 import java.util.Optional;
-import static com.github.javaparser.ast.Modifier.*;
+import java.util.function.Consumer;
 import static com.github.javaparser.ast.NodeList.nodeList;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import com.github.javaparser.resolution.Resolvable;
-import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
-import java.util.function.Consumer;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The declaration of a field in a class. "private static int a=15*15;" in this example: <code>class X { private static
@@ -67,27 +60,27 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class FieldDeclaration extends BodyDeclaration<FieldDeclaration> implements NodeWithJavadoc<FieldDeclaration>, NodeWithVariables<FieldDeclaration>, NodeWithAccessModifiers<FieldDeclaration>, NodeWithStaticModifier<FieldDeclaration>, NodeWithFinalModifier<FieldDeclaration>, Resolvable<ResolvedFieldDeclaration> {
+public class FieldDeclaration extends BodyDeclaration<FieldDeclaration> implements NodeWithJavadoc<FieldDeclaration>, NodeWithVariables<FieldDeclaration>, NodeWithAccessModifiers<FieldDeclaration>, NodeWithStaticModifier<FieldDeclaration>, NodeWithFinalModifier<FieldDeclaration>, Resolvable<ResolvedFieldDeclaration> {
 
-    private EnumSet<Modifier> modifiers;
+    private NodeList<Modifier> modifiers;
 
     @NonEmptyProperty
     private NodeList<VariableDeclarator> variables;
 
     public FieldDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new NodeList<>());
+        this(null, new NodeList<>(), new NodeList<>(), new NodeList<>());
     }
 
-    public FieldDeclaration(EnumSet<Modifier> modifiers, VariableDeclarator variable) {
+    public FieldDeclaration(NodeList<Modifier> modifiers, VariableDeclarator variable) {
         this(null, modifiers, new NodeList<>(), nodeList(variable));
     }
 
-    public FieldDeclaration(EnumSet<Modifier> modifiers, NodeList<VariableDeclarator> variables) {
+    public FieldDeclaration(NodeList<Modifier> modifiers, NodeList<VariableDeclarator> variables) {
         this(null, modifiers, new NodeList<>(), variables);
     }
 
     @AllFieldsConstructor
-    public FieldDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) {
+    public FieldDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) {
         this(null, modifiers, annotations, variables);
     }
 
@@ -95,7 +88,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public FieldDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) {
+    public FieldDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) {
         super(tokenRange, annotations);
         setModifiers(modifiers);
         setVariables(variables);
@@ -109,7 +102,7 @@
      * @param type type
      * @param name field name
      */
-    public FieldDeclaration(EnumSet<Modifier> modifiers, Type type, String name) {
+    public FieldDeclaration(NodeList<Modifier> modifiers, Type type, String name) {
         this(assertNotNull(modifiers), new VariableDeclarator(type, assertNotNull(name)));
     }
 
@@ -132,7 +125,7 @@
      * @see Modifier
      */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public EnumSet<Modifier> getModifiers() {
+    public NodeList<Modifier> getModifiers() {
         return modifiers;
     }
 
@@ -142,13 +135,16 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public FieldDeclaration setModifiers(final EnumSet<Modifier> modifiers) {
+    public FieldDeclaration setModifiers(final NodeList<Modifier> modifiers) {
         assertNotNull(modifiers);
         if (modifiers == this.modifiers) {
             return (FieldDeclaration) this;
         }
         notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
+        if (this.modifiers != null)
+            this.modifiers.setParentNode(null);
         this.modifiers = modifiers;
+        setAsParentNodeOf(modifiers);
         return this;
     }
 
@@ -177,15 +173,15 @@
     public MethodDeclaration createGetter() {
         if (getVariables().size() != 1)
             throw new IllegalStateException("You can use this only when the field declares only 1 variable name");
-        Optional<ClassOrInterfaceDeclaration> parentClass = getAncestorOfType(ClassOrInterfaceDeclaration.class);
-        Optional<EnumDeclaration> parentEnum = getAncestorOfType(EnumDeclaration.class);
+        Optional<ClassOrInterfaceDeclaration> parentClass = findAncestor(ClassOrInterfaceDeclaration.class);
+        Optional<EnumDeclaration> parentEnum = findAncestor(EnumDeclaration.class);
         if (!(parentClass.isPresent() || parentEnum.isPresent()) || (parentClass.isPresent() && parentClass.get().isInterface()))
             throw new IllegalStateException("You can use this only when the field is attached to a class or an enum");
         VariableDeclarator variable = getVariable(0);
         String fieldName = variable.getNameAsString();
         String fieldNameUpper = fieldName.toUpperCase().substring(0, 1) + fieldName.substring(1, fieldName.length());
         final MethodDeclaration getter;
-        getter = parentClass.map(clazz -> clazz.addMethod("get" + fieldNameUpper, PUBLIC)).orElseGet(() -> parentEnum.get().addMethod("get" + fieldNameUpper, PUBLIC));
+        getter = parentClass.map(clazz -> clazz.addMethod("get" + fieldNameUpper, Modifier.Keyword.PUBLIC)).orElseGet(() -> parentEnum.get().addMethod("get" + fieldNameUpper, Modifier.Keyword.PUBLIC));
         getter.setType(variable.getType());
         BlockStmt blockStmt = new BlockStmt();
         getter.setBody(blockStmt);
@@ -204,15 +200,15 @@
     public MethodDeclaration createSetter() {
         if (getVariables().size() != 1)
             throw new IllegalStateException("You can use this only when the field declares only 1 variable name");
-        Optional<ClassOrInterfaceDeclaration> parentClass = getAncestorOfType(ClassOrInterfaceDeclaration.class);
-        Optional<EnumDeclaration> parentEnum = getAncestorOfType(EnumDeclaration.class);
+        Optional<ClassOrInterfaceDeclaration> parentClass = findAncestor(ClassOrInterfaceDeclaration.class);
+        Optional<EnumDeclaration> parentEnum = findAncestor(EnumDeclaration.class);
         if (!(parentClass.isPresent() || parentEnum.isPresent()) || (parentClass.isPresent() && parentClass.get().isInterface()))
             throw new IllegalStateException("You can use this only when the field is attached to a class or an enum");
         VariableDeclarator variable = getVariable(0);
         String fieldName = variable.getNameAsString();
         String fieldNameUpper = fieldName.toUpperCase().substring(0, 1) + fieldName.substring(1, fieldName.length());
         final MethodDeclaration setter;
-        setter = parentClass.map(clazz -> clazz.addMethod("set" + fieldNameUpper, PUBLIC)).orElseGet(() -> parentEnum.get().addMethod("set" + fieldNameUpper, PUBLIC));
+        setter = parentClass.map(clazz -> clazz.addMethod("set" + fieldNameUpper, Modifier.Keyword.PUBLIC)).orElseGet(() -> parentEnum.get().addMethod("set" + fieldNameUpper, Modifier.Keyword.PUBLIC));
         setter.setType(new VoidType());
         setter.getParameters().add(new Parameter(variable.getType(), fieldName));
         BlockStmt blockStmt2 = new BlockStmt();
@@ -222,19 +218,19 @@
     }
 
     public boolean isTransient() {
-        return getModifiers().contains(TRANSIENT);
+        return hasModifier(Modifier.Keyword.TRANSIENT);
     }
 
     public boolean isVolatile() {
-        return getModifiers().contains(VOLATILE);
+        return hasModifier(Modifier.Keyword.VOLATILE);
     }
 
     public FieldDeclaration setTransient(boolean set) {
-        return setModifier(TRANSIENT, set);
+        return setModifier(Modifier.Keyword.TRANSIENT, set);
     }
 
     public FieldDeclaration setVolatile(boolean set) {
-        return setModifier(VOLATILE, set);
+        return setModifier(Modifier.Keyword.VOLATILE, set);
     }
 
     @Override
@@ -242,6 +238,12 @@
     public boolean remove(Node node) {
         if (node == null)
             return false;
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.remove(i);
+                return true;
+            }
+        }
         for (int i = 0; i < variables.size(); i++) {
             if (variables.get(i) == node) {
                 variables.remove(i);
@@ -268,6 +270,12 @@
     public boolean replace(Node node, Node replacementNode) {
         if (node == null)
             return false;
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.set(i, (Modifier) replacementNode);
+                return true;
+            }
+        }
         for (int i = 0; i < variables.size(); i++) {
             if (variables.get(i) == node) {
                 variables.set(i, (VariableDeclarator) replacementNode);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/InitializerDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/InitializerDeclaration.java
index 06fe78e..c1c4108 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/InitializerDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/InitializerDeclaration.java
@@ -21,31 +21,28 @@
 package com.github.javaparser.ast.body;
 
 import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.nodeTypes.NodeWithBlockStmt;
 import com.github.javaparser.ast.nodeTypes.NodeWithJavadoc;
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 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.InitializerDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A (possibly static) initializer body. "static { a=3; }" in this example: <code>class X { static { a=3; }  } </code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class InitializerDeclaration extends BodyDeclaration<InitializerDeclaration> implements NodeWithJavadoc<InitializerDeclaration>, NodeWithBlockStmt<InitializerDeclaration> {
+public class InitializerDeclaration extends BodyDeclaration<InitializerDeclaration> implements NodeWithJavadoc<InitializerDeclaration>, NodeWithBlockStmt<InitializerDeclaration> {
 
     private boolean isStatic;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java
index dff4cad..4a332c8 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/MethodDeclaration.java
@@ -20,10 +20,7 @@
  */
 package com.github.javaparser.ast.body;
 
-import com.github.javaparser.ast.AccessSpecifier;
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.expr.SimpleName;
 import com.github.javaparser.ast.nodeTypes.*;
@@ -36,31 +33,29 @@
 import com.github.javaparser.ast.type.TypeParameter;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.EnumSet;
 import java.util.Optional;
-import static com.github.javaparser.ast.Modifier.*;
 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.MethodDeclarationMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.resolution.Resolvable;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A method declaration. "public int abc() {return 1;}" in this example: <code>class X { public int abc() {return 1;}
  * }</code>
- *
+ * <p>
  * <br/>All annotations preceding the return type will be set on this object, not on the return type.
  * JavaParser doesn't know if it they are applicable to the method or the type.
  *
  * @author Julio Vilmar Gesser
  */
-public final class MethodDeclaration extends CallableDeclaration<MethodDeclaration> implements NodeWithType<MethodDeclaration, Type>, NodeWithOptionalBlockStmt<MethodDeclaration>, NodeWithJavadoc<MethodDeclaration>, NodeWithDeclaration, NodeWithSimpleName<MethodDeclaration>, NodeWithParameters<MethodDeclaration>, NodeWithThrownExceptions<MethodDeclaration>, NodeWithTypeParameters<MethodDeclaration>, NodeWithAccessModifiers<MethodDeclaration>, NodeWithAbstractModifier<MethodDeclaration>, NodeWithStaticModifier<MethodDeclaration>, NodeWithFinalModifier<MethodDeclaration>, NodeWithStrictfpModifier<MethodDeclaration>, Resolvable<ResolvedMethodDeclaration> {
+public class MethodDeclaration extends CallableDeclaration<MethodDeclaration> implements NodeWithType<MethodDeclaration, Type>, NodeWithOptionalBlockStmt<MethodDeclaration>, NodeWithJavadoc<MethodDeclaration>, NodeWithDeclaration, NodeWithSimpleName<MethodDeclaration>, NodeWithParameters<MethodDeclaration>, NodeWithThrownExceptions<MethodDeclaration>, NodeWithTypeParameters<MethodDeclaration>, NodeWithAccessModifiers<MethodDeclaration>, NodeWithAbstractModifier<MethodDeclaration>, NodeWithStaticModifier<MethodDeclaration>, NodeWithFinalModifier<MethodDeclaration>, NodeWithStrictfpModifier<MethodDeclaration>, Resolvable<ResolvedMethodDeclaration> {
 
     private Type type;
 
@@ -68,40 +63,31 @@
     private BlockStmt body;
 
     public MethodDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new NodeList<>(), new ClassOrInterfaceType(), new SimpleName(), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
+        this(null, new NodeList<>(), new NodeList<>(), new NodeList<>(), new ClassOrInterfaceType(), new SimpleName(), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
     }
 
-    public MethodDeclaration(final EnumSet<Modifier> modifiers, final Type type, final String name) {
+    public MethodDeclaration(final NodeList<Modifier> modifiers, final Type type, final String name) {
         this(null, modifiers, new NodeList<>(), new NodeList<>(), type, new SimpleName(name), new NodeList<>(), new NodeList<>(), new BlockStmt(), null);
     }
 
-    public MethodDeclaration(final EnumSet<Modifier> modifiers, final String name, final Type type, final NodeList<Parameter> parameters) {
+    public MethodDeclaration(final NodeList<Modifier> modifiers, final String name, final Type type, final NodeList<Parameter> parameters) {
         this(null, modifiers, new NodeList<>(), new NodeList<>(), type, new SimpleName(name), parameters, new NodeList<>(), new BlockStmt(), null);
     }
 
-    public MethodDeclaration(final EnumSet<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final NodeList<TypeParameter> typeParameters, final Type type, final SimpleName name, final NodeList<Parameter> parameters, final NodeList<ReferenceType> thrownExceptions, final BlockStmt body) {
+    public MethodDeclaration(final NodeList<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final NodeList<TypeParameter> typeParameters, final Type type, final SimpleName name, final NodeList<Parameter> parameters, final NodeList<ReferenceType> thrownExceptions, final BlockStmt body) {
         this(null, modifiers, annotations, typeParameters, type, name, parameters, thrownExceptions, body, null);
     }
 
     @AllFieldsConstructor
-    public MethodDeclaration(final EnumSet<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final NodeList<TypeParameter> typeParameters, final Type type, final SimpleName name, final NodeList<Parameter> parameters, final NodeList<ReferenceType> thrownExceptions, final BlockStmt body, ReceiverParameter receiverParameter) {
+    public MethodDeclaration(final NodeList<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final NodeList<TypeParameter> typeParameters, final Type type, final SimpleName name, final NodeList<Parameter> parameters, final NodeList<ReferenceType> thrownExceptions, final BlockStmt body, ReceiverParameter receiverParameter) {
         this(null, modifiers, annotations, typeParameters, type, name, parameters, thrownExceptions, body, receiverParameter);
     }
 
     /**
-     * @deprecated this constructor allows you to set "isDefault", but this is no longer a field of this node, but simply one of the modifiers. Use setDefault(boolean) or add DEFAULT to the modifiers set.
-     */
-    @Deprecated
-    public MethodDeclaration(final EnumSet<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final NodeList<TypeParameter> typeParameters, final Type type, final SimpleName name, final boolean isDefault, final NodeList<Parameter> parameters, final NodeList<ReferenceType> thrownExceptions, final BlockStmt body) {
-        this(null, modifiers, annotations, typeParameters, type, name, parameters, thrownExceptions, body, null);
-        setDefault(isDefault);
-    }
-
-    /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public MethodDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, Type type, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body, ReceiverParameter receiverParameter) {
+    public MethodDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, Type type, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, BlockStmt body, ReceiverParameter receiverParameter) {
         super(tokenRange, modifiers, annotations, typeParameters, name, parameters, thrownExceptions, receiverParameter);
         setType(type);
         setBody(body);
@@ -164,7 +150,7 @@
     }
 
     @Override
-    public MethodDeclaration setModifiers(final EnumSet<Modifier> modifiers) {
+    public MethodDeclaration setModifiers(final NodeList<Modifier> modifiers) {
         return super.setModifiers(modifiers);
     }
 
@@ -201,22 +187,21 @@
     public String getDeclarationAsString(boolean includingModifiers, boolean includingThrows, boolean includingParameterName) {
         StringBuilder sb = new StringBuilder();
         if (includingModifiers) {
-            AccessSpecifier accessSpecifier = getAccessSpecifier(getModifiers());
-            sb.append(accessSpecifier.asString());
-            sb.append(accessSpecifier == AccessSpecifier.DEFAULT ? "" : " ");
-            if (getModifiers().contains(STATIC)) {
+            AccessSpecifier accessSpecifier = getAccessSpecifier();
+            sb.append(accessSpecifier.asString()).append(" ");
+            if (isStatic()) {
                 sb.append("static ");
             }
-            if (getModifiers().contains(ABSTRACT)) {
+            if (isAbstract()) {
                 sb.append("abstract ");
             }
-            if (getModifiers().contains(FINAL)) {
+            if (isFinal()) {
                 sb.append("final ");
             }
-            if (getModifiers().contains(NATIVE)) {
+            if (isNative()) {
                 sb.append("native ");
             }
-            if (getModifiers().contains(SYNCHRONIZED)) {
+            if (isSynchronized()) {
                 sb.append("synchronized ");
             }
         }
@@ -246,27 +231,27 @@
     }
 
     public boolean isNative() {
-        return getModifiers().contains(NATIVE);
+        return hasModifier(Modifier.Keyword.NATIVE);
     }
 
     public boolean isSynchronized() {
-        return getModifiers().contains(SYNCHRONIZED);
+        return hasModifier(Modifier.Keyword.SYNCHRONIZED);
     }
 
     public boolean isDefault() {
-        return getModifiers().contains(DEFAULT);
+        return hasModifier(Modifier.Keyword.DEFAULT);
     }
 
     public MethodDeclaration setNative(boolean set) {
-        return setModifier(NATIVE, set);
+        return setModifier(Modifier.Keyword.NATIVE, set);
     }
 
     public MethodDeclaration setSynchronized(boolean set) {
-        return setModifier(SYNCHRONIZED, set);
+        return setModifier(Modifier.Keyword.SYNCHRONIZED, set);
     }
 
     public MethodDeclaration setDefault(boolean set) {
-        return setModifier(DEFAULT, set);
+        return setModifier(Modifier.Keyword.DEFAULT, set);
     }
 
     @Override
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/Parameter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/Parameter.java
index a7cf357..7fae444 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/Parameter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/Parameter.java
@@ -38,12 +38,11 @@
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.ParameterMetaModel;
-import java.util.EnumSet;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
 import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The parameters to a method or lambda. Lambda parameters may have inferred types, in that case "type" is UnknownType.
@@ -56,7 +55,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class Parameter extends Node implements NodeWithType<Parameter, Type>, NodeWithAnnotations<Parameter>, NodeWithSimpleName<Parameter>, NodeWithFinalModifier<Parameter>, Resolvable<ResolvedParameterDeclaration> {
+public class Parameter extends Node implements NodeWithType<Parameter, Type>, NodeWithAnnotations<Parameter>, NodeWithSimpleName<Parameter>, NodeWithFinalModifier<Parameter>, Resolvable<ResolvedParameterDeclaration> {
 
     private Type type;
 
@@ -64,18 +63,18 @@
 
     private NodeList<AnnotationExpr> varArgsAnnotations;
 
-    private EnumSet<Modifier> modifiers;
+    private NodeList<Modifier> modifiers;
 
     private NodeList<AnnotationExpr> annotations;
 
     private SimpleName name;
 
     public Parameter() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new ClassOrInterfaceType(), false, new NodeList<>(), new SimpleName());
+        this(null, new NodeList<>(), new NodeList<>(), new ClassOrInterfaceType(), false, new NodeList<>(), new SimpleName());
     }
 
     public Parameter(Type type, SimpleName name) {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), type, false, new NodeList<>(), name);
+        this(null, new NodeList<>(), new NodeList<>(), type, false, new NodeList<>(), name);
     }
 
     /**
@@ -85,15 +84,15 @@
      * @param name name of the parameter
      */
     public Parameter(Type type, String name) {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), type, false, new NodeList<>(), new SimpleName(name));
+        this(null, new NodeList<>(), new NodeList<>(), type, false, new NodeList<>(), new SimpleName(name));
     }
 
-    public Parameter(EnumSet<Modifier> modifiers, Type type, SimpleName name) {
+    public Parameter(NodeList<Modifier> modifiers, Type type, SimpleName name) {
         this(null, modifiers, new NodeList<>(), type, false, new NodeList<>(), name);
     }
 
     @AllFieldsConstructor
-    public Parameter(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, boolean isVarArgs, NodeList<AnnotationExpr> varArgsAnnotations, SimpleName name) {
+    public Parameter(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, boolean isVarArgs, NodeList<AnnotationExpr> varArgsAnnotations, SimpleName name) {
         this(null, modifiers, annotations, type, isVarArgs, varArgsAnnotations, name);
     }
 
@@ -101,7 +100,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public Parameter(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, boolean isVarArgs, NodeList<AnnotationExpr> varArgsAnnotations, SimpleName name) {
+    public Parameter(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, Type type, boolean isVarArgs, NodeList<AnnotationExpr> varArgsAnnotations, SimpleName name) {
         super(tokenRange);
         setModifiers(modifiers);
         setAnnotations(annotations);
@@ -178,7 +177,7 @@
      * @see Modifier
      */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public EnumSet<Modifier> getModifiers() {
+    public NodeList<Modifier> getModifiers() {
         return modifiers;
     }
 
@@ -215,13 +214,16 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Parameter setModifiers(final EnumSet<Modifier> modifiers) {
+    public Parameter setModifiers(final NodeList<Modifier> modifiers) {
         assertNotNull(modifiers);
         if (modifiers == this.modifiers) {
             return (Parameter) this;
         }
         notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
+        if (this.modifiers != null)
+            this.modifiers.setParentNode(null);
         this.modifiers = modifiers;
+        setAsParentNodeOf(modifiers);
         return this;
     }
 
@@ -236,6 +238,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.remove(i);
+                return true;
+            }
+        }
         for (int i = 0; i < varArgsAnnotations.size(); i++) {
             if (varArgsAnnotations.get(i) == node) {
                 varArgsAnnotations.remove(i);
@@ -287,6 +295,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.set(i, (Modifier) replacementNode);
+                return true;
+            }
+        }
         if (node == name) {
             setName((SimpleName) replacementNode);
             return true;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/ReceiverParameter.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/ReceiverParameter.java
index b0038e1..0e14f1a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/ReceiverParameter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/ReceiverParameter.java
@@ -22,17 +22,13 @@
 
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.expr.SimpleName;
 import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
 import com.github.javaparser.ast.nodeTypes.NodeWithName;
-import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
 import com.github.javaparser.ast.nodeTypes.NodeWithType;
-import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithFinalModifier;
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.ast.type.Type;
@@ -40,11 +36,9 @@
 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.ParameterMetaModel;
-import javax.annotation.Generated;
-import java.util.EnumSet;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import com.github.javaparser.metamodel.ReceiverParameterMetaModel;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The rather obscure <a href="http://blog.joda.org/2015/12/explicit-receiver-parameters.html">"receiver parameter" feature of Java</a>.
@@ -54,7 +48,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ReceiverParameter extends Node implements NodeWithType<ReceiverParameter, Type>, NodeWithAnnotations<ReceiverParameter>, NodeWithName<ReceiverParameter> {
+public class ReceiverParameter extends Node implements NodeWithType<ReceiverParameter, Type>, NodeWithAnnotations<ReceiverParameter>, NodeWithName<ReceiverParameter> {
 
     private Type type;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/TypeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/TypeDeclaration.java
index 06f9753..eca15c2 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/TypeDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/TypeDeclaration.java
@@ -34,14 +34,13 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.TypeDeclarationMetaModel;
-import javax.annotation.Generated;
-import java.util.EnumSet;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import java.util.List;
+import java.util.Optional;
 import java.util.function.Consumer;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import static java.util.stream.Collectors.toList;
 import com.github.javaparser.ast.Node;
-import java.util.Optional;
 
 /**
  * A base class for all types of type declarations.
@@ -52,20 +51,20 @@
 
     private SimpleName name;
 
-    private EnumSet<Modifier> modifiers;
+    private NodeList<Modifier> modifiers;
 
     private NodeList<BodyDeclaration<?>> members;
 
     public TypeDeclaration() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new SimpleName(), new NodeList<>());
+        this(null, new NodeList<>(), new NodeList<>(), new SimpleName(), new NodeList<>());
     }
 
-    public TypeDeclaration(EnumSet<Modifier> modifiers, String name) {
+    public TypeDeclaration(NodeList<Modifier> modifiers, String name) {
         this(null, modifiers, new NodeList<>(), new SimpleName(name), new NodeList<>());
     }
 
     @AllFieldsConstructor
-    public TypeDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
+    public TypeDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
         this(null, modifiers, annotations, name, members);
     }
 
@@ -73,7 +72,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public TypeDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
+    public TypeDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, SimpleName name, NodeList<BodyDeclaration<?>> members) {
         super(tokenRange, annotations);
         setModifiers(modifiers);
         setName(name);
@@ -104,7 +103,7 @@
      * @see Modifier
      */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public EnumSet<Modifier> getModifiers() {
+    public NodeList<Modifier> getModifiers() {
         return modifiers;
     }
 
@@ -125,13 +124,16 @@
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
     @SuppressWarnings("unchecked")
-    public T setModifiers(final EnumSet<Modifier> modifiers) {
+    public T setModifiers(final NodeList<Modifier> modifiers) {
         assertNotNull(modifiers);
         if (modifiers == this.modifiers) {
             return (T) this;
         }
         notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
+        if (this.modifiers != null)
+            this.modifiers.setParentNode(null);
         this.modifiers = modifiers;
+        setAsParentNodeOf(modifiers);
         return (T) this;
     }
 
@@ -166,6 +168,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.remove(i);
+                return true;
+            }
+        }
         return super.remove(node);
     }
 
@@ -184,6 +192,19 @@
     }
 
     /**
+     * Returns the fully qualified name of this type, derived only from information available in this compilation unit. (So no symbol solving happens.)
+     * If the declared type is a local class declaration, it will return Optional.empty().
+     * If the declared type is not contained in a compilation unit, it will return Optional.empty().
+     * @see com.github.javaparser.ast.stmt.LocalClassDeclarationStmt
+     */
+    public Optional<String> getFullyQualifiedName() {
+        if (isTopLevelType()) {
+            return findCompilationUnit().map(cu -> cu.getPackageDeclaration().map(pd -> pd.getNameAsString()).map(pkg -> pkg + "." + getNameAsString()).orElse(getNameAsString()));
+        }
+        return findAncestor(TypeDeclaration.class).map(td -> (TypeDeclaration<?>) td).flatMap(td -> td.getFullyQualifiedName().map(fqn -> fqn + "." + getNameAsString()));
+    }
+
+    /**
      * @return is this type's parent a TypeDeclaration?
      * NOTE: many people are confused over terminology. Refer to https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html .
      */
@@ -214,6 +235,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.set(i, (Modifier) replacementNode);
+                return true;
+            }
+        }
         if (node == name) {
             setName((SimpleName) replacementNode);
             return true;
@@ -243,4 +270,6 @@
     public Optional<TypeDeclaration> toTypeDeclaration() {
         return Optional.of(this);
     }
+
+    public abstract ResolvedReferenceTypeDeclaration resolve();
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/body/VariableDeclarator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/body/VariableDeclarator.java
index 0d342ac..0ec9226 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/body/VariableDeclarator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/body/VariableDeclarator.java
@@ -44,10 +44,10 @@
 import java.util.Optional;
 import static com.github.javaparser.utils.Utils.assertNonEmpty;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
-import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The declaration of a variable.<br/>In <code>int x = 14, y = 3;</code> "int x = 14"  and "int y = 3"  are
@@ -56,7 +56,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class VariableDeclarator extends Node implements NodeWithType<VariableDeclarator, Type>, NodeWithSimpleName<VariableDeclarator>, Resolvable<ResolvedFieldDeclaration> {
+public class VariableDeclarator extends Node implements NodeWithType<VariableDeclarator, Type>, NodeWithSimpleName<VariableDeclarator>, Resolvable<ResolvedValueDeclaration> {
 
     private SimpleName name;
 
@@ -117,7 +117,7 @@
                 if (property == ObservableProperty.TYPE) {
                     VariableDeclarator vd = VariableDeclarator.this;
                     if (vd.getParentNode().isPresent() && vd.getParentNode().get() instanceof NodeWithVariables) {
-                        NodeWithVariables nodeWithVariables = (NodeWithVariables) vd.getParentNode().get();
+                        NodeWithVariables<?> nodeWithVariables = (NodeWithVariables<?>) vd.getParentNode().get();
                         // We calculate the value the property will assume after the change will be completed
                         Optional<Type> currentMaxCommonType = nodeWithVariables.getMaximumCommonType();
                         List<Type> types = new LinkedList<>();
@@ -275,7 +275,7 @@
     }
 
     @Override
-    public ResolvedFieldDeclaration resolve() {
-        return getSymbolResolver().resolveDeclaration(this, ResolvedFieldDeclaration.class);
+    public ResolvedValueDeclaration resolve() {
+        return getSymbolResolver().resolveDeclaration(this, ResolvedValueDeclaration.class);
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/BlockComment.java b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/BlockComment.java
index 8d30b28..e14c2d8 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/BlockComment.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/BlockComment.java
@@ -27,10 +27,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.BlockCommentMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <p>
@@ -41,7 +41,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class BlockComment extends Comment {
+public class BlockComment extends Comment {
 
     public BlockComment() {
         this(null, "empty");
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java
index 0c5f6b4..86a4560 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/Comment.java
@@ -29,8 +29,8 @@
 import com.github.javaparser.metamodel.CommentMetaModel;
 import com.github.javaparser.metamodel.InternalProperty;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 
@@ -131,6 +131,15 @@
     }
 
     @Override
+    public Node setComment(final Comment comment) {
+        // comments on comments are not allowed, so we override setComment(Comment) here
+        if (comment != null) {
+            throw new IllegalArgumentException("A comment cannot be commented.");
+        }
+        return super.setComment(comment);
+    }
+
+    @Override
     public boolean remove() {
         // the other are orphan comments and remove should work with them
         if (this.commentedNode != null) {
@@ -143,6 +152,16 @@
         }
     }
 
+   @Override
+    public Node findRootNode() {
+       // (Non-orphan) comments are not integrated into the normal AST; we need to get the commented node first.
+        Node n = getCommentedNode().orElse(this);
+        while (n.getParentNode().isPresent()) {
+            n = n.getParentNode().get();
+        }
+        return n;
+    }
+
     @Override
     @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
     public boolean remove(Node node) {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/JavadocComment.java b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/JavadocComment.java
index d795997..070823c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/JavadocComment.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/JavadocComment.java
@@ -20,7 +20,6 @@
  */
 package com.github.javaparser.ast.comments;
 
-import com.github.javaparser.JavaParser;
 import com.github.javaparser.ast.AllFieldsConstructor;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
@@ -29,17 +28,18 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.JavadocCommentMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
+import static com.github.javaparser.StaticJavaParser.parseJavadoc;
 
 /**
  * A Javadoc comment. <code>/&#42;&#42; a comment &#42;/</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class JavadocComment extends Comment {
+public class JavadocComment extends Comment {
 
     public JavadocComment() {
         this(null, "empty");
@@ -72,7 +72,7 @@
     }
 
     public Javadoc parse() {
-        return JavaParser.parseJavadoc(getContent());
+        return parseJavadoc(getContent());
     }
 
     @Override
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/LineComment.java b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/LineComment.java
index ddbce80..ce2d7f3 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/comments/LineComment.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/comments/LineComment.java
@@ -27,10 +27,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.LineCommentMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <p>
@@ -40,7 +40,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class LineComment extends Comment {
+public class LineComment extends Comment {
 
     public LineComment() {
         this(null, "empty");
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AnnotationExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AnnotationExpr.java
index 31c70fb..86aecd7 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AnnotationExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/AnnotationExpr.java
@@ -20,25 +20,28 @@
  */
 package com.github.javaparser.ast.expr;
 
+import com.github.javaparser.TokenRange;
 import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Generated;
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithName;
 import com.github.javaparser.ast.observer.ObservableProperty;
-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.AnnotationExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
+import com.github.javaparser.resolution.Resolvable;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedAnnotationDeclaration;
 import java.util.Optional;
+import java.util.function.Consumer;
+import static com.github.javaparser.utils.Utils.assertNotNull;
 
 /**
  * A base class for the different types of annotations.
  *
  * @author Julio Vilmar Gesser
  */
-public abstract class AnnotationExpr extends Expression implements NodeWithName<AnnotationExpr> {
+public abstract class AnnotationExpr extends Expression implements NodeWithName<AnnotationExpr>, Resolvable<ResolvedAnnotationDeclaration> {
 
     protected Name name;
 
@@ -129,6 +132,20 @@
         action.accept(this);
     }
 
+    /**
+     * Attempts to resolve the declaration corresponding to the annotation expression. If successful, a
+     * {@link ResolvedAnnotationDeclaration} representing the declaration of the annotation referenced by this
+     * {@code AnnotationExpr} is returned. Otherwise, an {@link UnsolvedSymbolException} is thrown.
+     *
+     * @return a {@link ResolvedAnnotationDeclaration} representing the declaration of the annotation expression.
+     * @throws UnsolvedSymbolException if the declaration corresponding to the annotation expression could not be
+     *                                 resolved.
+     */
+    @Override
+    public ResolvedAnnotationDeclaration resolve() {
+        return getSymbolResolver().resolveDeclaration(this, ResolvedAnnotationDeclaration.class);
+    }
+
     @Override
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public Optional<AnnotationExpr> toAnnotationExpr() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayAccessExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayAccessExpr.java
index 6945dd9..1e62ab1 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayAccessExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayAccessExpr.java
@@ -29,10 +29,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ArrayAccessExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Array brackets [] being used to get a value from an array.
@@ -40,7 +40,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ArrayAccessExpr extends Expression {
+public class ArrayAccessExpr extends Expression {
 
     private Expression name;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayCreationExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayCreationExpr.java
index 5099258..905cb02 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayCreationExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayCreationExpr.java
@@ -20,7 +20,6 @@
  */
 package com.github.javaparser.ast.expr;
 
-import com.github.javaparser.Range;
 import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.type.ArrayType;
@@ -32,16 +31,14 @@
 import com.github.javaparser.metamodel.ArrayCreationExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.NonEmptyProperty;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Optional;
-import static com.github.javaparser.JavaParser.parseType;
+import static com.github.javaparser.StaticJavaParser.parseType;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
-import com.github.javaparser.ast.Node;
 import com.github.javaparser.metamodel.OptionalProperty;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <code>new int[5][4][][]</code> or <code>new int[][]{{1},{2,3}}</code>.
@@ -51,7 +48,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ArrayCreationExpr extends Expression {
+public class ArrayCreationExpr extends Expression {
 
     @NonEmptyProperty
     private NodeList<ArrayCreationLevel> levels;
@@ -75,15 +72,6 @@
     }
 
     /**
-     * @deprecated range shouldn't be in utility constructors.
-     */
-    @Deprecated
-    public ArrayCreationExpr(Range range, Type elementType) {
-        this(null, elementType, new NodeList<>(), new ArrayInitializerExpr());
-        setRange(range);
-    }
-
-    /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayInitializerExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayInitializerExpr.java
index d585a18..b460b3d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayInitializerExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ArrayInitializerExpr.java
@@ -25,17 +25,15 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 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.ArrayInitializerExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The initialization of an array. In the following sample, the outer { } is an ArrayInitializerExpr.
@@ -45,7 +43,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ArrayInitializerExpr extends Expression {
+public class ArrayInitializerExpr extends Expression {
 
     private NodeList<Expression> values;
 
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 fbb4687..aae7b34 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
@@ -30,10 +30,10 @@
 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;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An assignment expression. It supports the operators that are found the the AssignExpr.Operator enum.
@@ -45,7 +45,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class AssignExpr extends Expression {
+public class AssignExpr extends Expression {
 
     public enum Operator implements Printable {
 
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 5ec79c0..9c4f56d 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
@@ -30,10 +30,10 @@
 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;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An expression with an expression on the left, an expression on the right, and an operator in the middle.
@@ -43,7 +43,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class BinaryExpr extends Expression {
+public class BinaryExpr extends Expression {
 
     public enum Operator implements Printable {
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BooleanLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BooleanLiteralExpr.java
index 4be43b2..f9777e2 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BooleanLiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/BooleanLiteralExpr.java
@@ -28,10 +28,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.BooleanLiteralExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The boolean literals.
@@ -40,7 +40,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class BooleanLiteralExpr extends LiteralExpr {
+public class BooleanLiteralExpr extends LiteralExpr {
 
     private boolean value;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CastExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CastExpr.java
index 174d24c..1f3fad4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CastExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CastExpr.java
@@ -33,17 +33,17 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.CastExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A typecast. The (long) in <code>(long)15</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class CastExpr extends Expression implements NodeWithType<CastExpr, Type>, NodeWithExpression<CastExpr> {
+public class CastExpr extends Expression implements NodeWithType<CastExpr, Type>, NodeWithExpression<CastExpr> {
 
     private Type type;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CharLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CharLiteralExpr.java
index bc2db00..7cdbd4c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CharLiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/CharLiteralExpr.java
@@ -29,10 +29,10 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.utils.StringEscapeUtils;
 import com.github.javaparser.utils.Utils;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A literal character.
@@ -44,7 +44,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class CharLiteralExpr extends LiteralStringValueExpr {
+public class CharLiteralExpr extends LiteralStringValueExpr {
 
     public CharLiteralExpr() {
         this(null, "?");
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ClassExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ClassExpr.java
index 729bd4f..ba826f8 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ClassExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ClassExpr.java
@@ -32,10 +32,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ClassExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Defines an expression that accesses the class of a type.
@@ -43,7 +43,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ClassExpr extends Expression implements NodeWithType<ClassExpr, Type> {
+public class ClassExpr extends Expression implements NodeWithType<ClassExpr, Type> {
 
     private Type type;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ConditionalExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ConditionalExpr.java
index bdc50a0..3aef1de 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ConditionalExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ConditionalExpr.java
@@ -30,10 +30,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ConditionalExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The ternary conditional expression.
@@ -41,7 +41,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ConditionalExpr extends Expression implements NodeWithCondition<ConditionalExpr> {
+public class ConditionalExpr extends Expression implements NodeWithCondition<ConditionalExpr> {
 
     private Expression condition;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/DoubleLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/DoubleLiteralExpr.java
index 007fdf3..0df773b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/DoubleLiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/DoubleLiteralExpr.java
@@ -27,10 +27,10 @@
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.metamodel.DoubleLiteralExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A float or a double constant. This value is stored exactly as found in the source.
@@ -40,7 +40,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class DoubleLiteralExpr extends LiteralStringValueExpr {
+public class DoubleLiteralExpr extends LiteralStringValueExpr {
 
     public DoubleLiteralExpr() {
         this(null, "0");
@@ -88,7 +88,11 @@
      * @return the literal value as a double
      */
     public double asDouble() {
-        return Double.parseDouble(value);
+        // Underscores are allowed in number literals for readability reasons but cause a NumberFormatException if
+        // passed along to Double#parseDouble. Hence, we apply a simple filter to remove all underscores.
+        // See https://github.com/javaparser/javaparser/issues/1980 for more information.
+        String noUnderscoreValue = value.replaceAll("_", "");
+        return Double.parseDouble(noUnderscoreValue);
     }
 
     public DoubleLiteralExpr setDouble(double value) {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/EnclosedExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/EnclosedExpr.java
index c3d56d8..7f5fb04 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/EnclosedExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/EnclosedExpr.java
@@ -29,10 +29,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.EnclosedExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An expression between ( ).
@@ -40,7 +40,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class EnclosedExpr extends Expression {
+public class EnclosedExpr extends Expression {
 
     private Expression inner;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Expression.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Expression.java
index de9e52b..448ff03 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Expression.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Expression.java
@@ -25,9 +25,9 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ExpressionMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import java.util.Optional;
@@ -557,6 +557,9 @@
     public void ifVariableDeclarationExpr(Consumer<VariableDeclarationExpr> action) {
     }
 
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
     public ResolvedType calculateResolvedType() {
         return getSymbolResolver().calculateType(this);
     }
@@ -730,4 +733,23 @@
     public Optional<VariableDeclarationExpr> toVariableDeclarationExpr() {
         return Optional.empty();
     }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isSwitchExpr() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public SwitchExpr asSwitchExpr() {
+        throw new IllegalStateException(f("%s is not an SwitchExpr", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<SwitchExpr> toSwitchExpr() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifSwitchExpr(Consumer<SwitchExpr> action) {
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/FieldAccessExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/FieldAccessExpr.java
index c6b9e0a..c7a3ec3 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/FieldAccessExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/FieldAccessExpr.java
@@ -26,6 +26,7 @@
 import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
 import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
@@ -35,18 +36,21 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.FieldAccessExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
+import com.github.javaparser.resolution.Resolvable;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
- * Access of a field of an object.
+ * Access of a field of an object or a class.
  * <br/>In <code>person.name</code> "name" is the name and "person" is the scope.
  *
  * @author Julio Vilmar Gesser
  */
-public final class FieldAccessExpr extends Expression implements NodeWithSimpleName<FieldAccessExpr>, NodeWithTypeArguments<FieldAccessExpr>, NodeWithScope<FieldAccessExpr> {
+public class FieldAccessExpr extends Expression implements NodeWithSimpleName<FieldAccessExpr>, NodeWithTypeArguments<FieldAccessExpr>, NodeWithScope<FieldAccessExpr>, Resolvable<ResolvedValueDeclaration> {
 
     private Expression scope;
 
@@ -56,11 +60,11 @@
     private SimpleName name;
 
     public FieldAccessExpr() {
-        this(null, new ThisExpr(), new NodeList<>(), new SimpleName());
+        this(null, new ThisExpr(), null, new SimpleName());
     }
 
     public FieldAccessExpr(final Expression scope, final String name) {
-        this(null, scope, new NodeList<>(), new SimpleName(name));
+        this(null, scope, null, new SimpleName(name));
     }
 
     @AllFieldsConstructor
@@ -111,37 +115,12 @@
         return this;
     }
 
-    /**
-     * Use {@link #getName} instead.
-     */
-    @Deprecated
-    public SimpleName getField() {
-        return name;
-    }
-
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
     public Expression getScope() {
         return scope;
     }
 
     /**
-     * Use {@link #setName} with new SimpleName(field) instead.
-     */
-    @Deprecated
-    public FieldAccessExpr setField(final String field) {
-        setName(new SimpleName(field));
-        return this;
-    }
-
-    /**
-     * Use {@link #setName} instead.
-     */
-    @Deprecated
-    public FieldAccessExpr setFieldExpr(SimpleName inner) {
-        return setName(inner);
-    }
-
-    /**
      * Sets the scope
      *
      * @param scope the scope, can not be null
@@ -254,9 +233,41 @@
         action.accept(this);
     }
 
+    /**
+     * Attempts to resolve the declaration corresponding to the accessed field. If successful, a
+     * {@link ResolvedValueDeclaration} representing the declaration of the value accessed by this
+     * {@code FieldAccessExpr} is returned. Otherwise, an {@link UnsolvedSymbolException} is thrown.
+     *
+     * @return a {@link ResolvedValueDeclaration} representing the declaration of the accessed value.
+     * @throws UnsolvedSymbolException if the declaration corresponding to the field access expression could not be
+     *                                 resolved.
+     * @see NameExpr#resolve()
+     * @see MethodCallExpr#resolve()
+     * @see ObjectCreationExpr#resolve()
+     * @see ExplicitConstructorInvocationStmt#resolve()
+     */
+    @Override
+    public ResolvedValueDeclaration resolve() {
+        return getSymbolResolver().resolveDeclaration(this, ResolvedValueDeclaration.class);
+    }
+
     @Override
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public Optional<FieldAccessExpr> toFieldAccessExpr() {
         return Optional.of(this);
     }
+
+    /**
+     * Indicate if this FieldAccessExpr is an element directly contained in a larger FieldAccessExpr.
+     */
+    public boolean isInternal() {
+        return this.getParentNode().isPresent() && this.getParentNode().get() instanceof FieldAccessExpr;
+    }
+
+    /**
+     * Indicate if this FieldAccessExpr is top level, i.e., it is not directly contained in a larger FieldAccessExpr.
+     */
+    public boolean isTopLevel() {
+        return !isInternal();
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java
index 69a505b..df173cc 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/InstanceOfExpr.java
@@ -33,10 +33,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.InstanceOfExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Usage of the instanceof operator.
@@ -44,7 +44,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class InstanceOfExpr extends Expression implements NodeWithType<InstanceOfExpr, ReferenceType>, NodeWithExpression<InstanceOfExpr> {
+public class InstanceOfExpr extends Expression implements NodeWithType<InstanceOfExpr, ReferenceType>, NodeWithExpression<InstanceOfExpr> {
 
     private Expression expression;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java
index a0d3949..a98e033 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/IntegerLiteralExpr.java
@@ -27,10 +27,10 @@
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.metamodel.IntegerLiteralExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * All ways to specify an int literal.
@@ -42,7 +42,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class IntegerLiteralExpr extends LiteralStringValueExpr {
+public class IntegerLiteralExpr extends LiteralStringValueExpr {
 
     public IntegerLiteralExpr() {
         this(null, "0");
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java
index a69176f..201c40e 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LambdaExpr.java
@@ -20,26 +20,27 @@
  */
 package com.github.javaparser.ast.expr;
 
+import com.github.javaparser.TokenRange;
 import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Generated;
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.body.Parameter;
 import com.github.javaparser.ast.nodeTypes.NodeWithParameters;
 import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.ast.stmt.ExpressionStmt;
 import com.github.javaparser.ast.stmt.ReturnStmt;
 import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Optional;
-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.DerivedProperty;
-import com.github.javaparser.metamodel.LambdaExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
+import com.github.javaparser.metamodel.LambdaExprMetaModel;
+import java.util.Optional;
 import java.util.function.Consumer;
+import static com.github.javaparser.utils.Utils.assertNotNull;
 
 /**
  * <h1>A lambda expression</h1>
@@ -53,11 +54,11 @@
  * If a parameter uses type inference (it has no type specified) then its type is set to <code>UnknownType</code>.
  * If they are in ( ), "isEnclosingParameters" is true.
  * <br/>The body is to the right of the ->.
- * The body is either a BlockStatement when it is in { } braces, or an ExpressionStatement when it is not in braces.
+ * The body is either a BlockStmt when it is in { } braces, or an ExpressionStmt when it is not in braces.
  *
  * @author Raquel Pau
  */
-public final class LambdaExpr extends Expression implements NodeWithParameters<LambdaExpr> {
+public class LambdaExpr extends Expression implements NodeWithParameters<LambdaExpr> {
 
     private NodeList<Parameter> parameters;
 
@@ -69,6 +70,34 @@
         this(null, new NodeList<>(), new ReturnStmt(), false);
     }
 
+    /**
+     * Creates a single parameter lambda expression.
+     */
+    public LambdaExpr(Parameter parameter, BlockStmt body) {
+        this(null, new NodeList<>(parameter), body, false);
+    }
+
+    /**
+     * Creates a zero or multi-parameter lambda expression with its parameters wrapped in ( ).
+     */
+    public LambdaExpr(NodeList<Parameter> parameters, BlockStmt body) {
+        this(null, parameters, body, true);
+    }
+
+    /**
+     * Creates a single parameter lambda expression.
+     */
+    public LambdaExpr(Parameter parameter, Expression body) {
+        this(null, new NodeList<>(parameter), new ExpressionStmt(body), false);
+    }
+
+    /**
+     * Creates a zero or multi-parameter lambda expression with its parameters wrapped in ( ).
+     */
+    public LambdaExpr(NodeList<Parameter> parameters, Expression body) {
+        this(null, parameters, new ExpressionStmt(body), true);
+    }
+
     @AllFieldsConstructor
     public LambdaExpr(NodeList<Parameter> parameters, Statement body, boolean isEnclosingParameters) {
         this(null, parameters, body, isEnclosingParameters);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralExpr.java
index 2c81560..1eac504 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralExpr.java
@@ -25,8 +25,8 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.LiteralExprMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 import java.util.Optional;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralStringValueExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralStringValueExpr.java
index 4956146..35073ac 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralStringValueExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LiteralStringValueExpr.java
@@ -27,8 +27,8 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.LiteralStringValueExprMetaModel;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 import java.util.Optional;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java
index d15442f..bd5022a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/LongLiteralExpr.java
@@ -27,10 +27,10 @@
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.LongLiteralExprMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * All ways to specify a long literal.
@@ -42,7 +42,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class LongLiteralExpr extends LiteralStringValueExpr {
+public class LongLiteralExpr extends LiteralStringValueExpr {
 
     public LongLiteralExpr() {
         this(null, "0");
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MarkerAnnotationExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MarkerAnnotationExpr.java
index e9ab894..b4854e3 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MarkerAnnotationExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MarkerAnnotationExpr.java
@@ -27,11 +27,11 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.MarkerAnnotationExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import static com.github.javaparser.JavaParser.parseName;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
+import static com.github.javaparser.StaticJavaParser.parseName;
 
 /**
  * An annotation that uses only the annotation type name.
@@ -39,7 +39,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class MarkerAnnotationExpr extends AnnotationExpr {
+public class MarkerAnnotationExpr extends AnnotationExpr {
 
     public MarkerAnnotationExpr() {
         this(null, new Name());
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MemberValuePair.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MemberValuePair.java
index 8accb7b..b1fd322 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MemberValuePair.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MemberValuePair.java
@@ -30,8 +30,8 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.MemberValuePairMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A value for a member of an annotation.
@@ -39,7 +39,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class MemberValuePair extends Node implements NodeWithSimpleName<MemberValuePair> {
+public class MemberValuePair extends Node implements NodeWithSimpleName<MemberValuePair> {
 
     private SimpleName name;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodCallExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodCallExpr.java
index dc914c9..e87c1ae 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodCallExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodCallExpr.java
@@ -27,6 +27,7 @@
 import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
 import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
@@ -36,20 +37,21 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.MethodCallExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
-import com.github.javaparser.resolution.SymbolResolver;
+import com.github.javaparser.resolution.Resolvable;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
- * A method call on an object. <br/><code>circle.circumference()</code> <br/>In <code>a.&lt;String&gt;bb(15);</code> a
+ * A method call on an object or a class. <br/><code>circle.circumference()</code> <br/>In <code>a.&lt;String&gt;bb(15);</code> a
  * is the scope, String is a type argument, bb is the name and 15 is an argument.
  *
  * @author Julio Vilmar Gesser
  */
-public final class MethodCallExpr extends Expression implements NodeWithTypeArguments<MethodCallExpr>, NodeWithArguments<MethodCallExpr>, NodeWithSimpleName<MethodCallExpr>, NodeWithOptionalScope<MethodCallExpr> {
+public class MethodCallExpr extends Expression implements NodeWithTypeArguments<MethodCallExpr>, NodeWithArguments<MethodCallExpr>, NodeWithSimpleName<MethodCallExpr>, NodeWithOptionalScope<MethodCallExpr>, Resolvable<ResolvedMethodDeclaration> {
 
     @OptionalProperty
     private Expression scope;
@@ -62,27 +64,31 @@
     private NodeList<Expression> arguments;
 
     public MethodCallExpr() {
-        this(null, null, new NodeList<>(), new SimpleName(), new NodeList<>());
+        this(null, null, null, new SimpleName(), new NodeList<>());
     }
 
     public MethodCallExpr(String name, Expression... arguments) {
-        this(null, null, new NodeList<>(), new SimpleName(name), new NodeList<>(arguments));
+        this(null, null, null, new SimpleName(name), new NodeList<>(arguments));
     }
 
     public MethodCallExpr(final Expression scope, final String name) {
-        this(null, scope, new NodeList<>(), new SimpleName(name), new NodeList<>());
+        this(null, scope, null, new SimpleName(name), new NodeList<>());
     }
 
     public MethodCallExpr(final Expression scope, final SimpleName name) {
-        this(null, scope, new NodeList<>(), name, new NodeList<>());
+        this(null, scope, null, name, new NodeList<>());
     }
 
     public MethodCallExpr(final Expression scope, final String name, final NodeList<Expression> arguments) {
-        this(null, scope, new NodeList<>(), new SimpleName(name), arguments);
+        this(null, scope, null, new SimpleName(name), arguments);
+    }
+
+    public MethodCallExpr(final Expression scope, final NodeList<Type> typeArguments, final String name, final NodeList<Expression> arguments) {
+        this(null, scope, typeArguments, new SimpleName(name), arguments);
     }
 
     public MethodCallExpr(final Expression scope, final SimpleName name, final NodeList<Expression> arguments) {
-        this(null, scope, new NodeList<>(), name, arguments);
+        this(null, scope, null, name, arguments);
     }
 
     @AllFieldsConstructor
@@ -289,7 +295,21 @@
         action.accept(this);
     }
 
-    public ResolvedMethodDeclaration resolveInvokedMethod() {
+    /**
+     * Attempts to resolve the declaration corresponding to the invoked method. If successful, a
+     * {@link ResolvedMethodDeclaration} representing the declaration of the constructor invoked by this
+     * {@code MethodCallExpr} is returned. Otherwise, an {@link UnsolvedSymbolException} is thrown.
+     *
+     * @return a {@link ResolvedMethodDeclaration} representing the declaration of the invoked method.
+     * @throws UnsolvedSymbolException if the declaration corresponding to the method call expression could not be
+     *                                 resolved.
+     * @see NameExpr#resolve()
+     * @see FieldAccessExpr#resolve()
+     * @see ObjectCreationExpr#resolve()
+     * @see ExplicitConstructorInvocationStmt#resolve()
+     */
+    @Override
+    public ResolvedMethodDeclaration resolve() {
         return getSymbolResolver().resolveDeclaration(this, ResolvedMethodDeclaration.class);
     }
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodReferenceExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodReferenceExpr.java
index 8ddaac00..a0c1e78 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodReferenceExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/MethodReferenceExpr.java
@@ -28,8 +28,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.assertNonEmpty;
 import static com.github.javaparser.utils.Utils.assertNotNull;
@@ -38,10 +36,10 @@
 import com.github.javaparser.metamodel.MethodReferenceExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.NonEmptyProperty;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Method reference expressions introduced in Java 8 specifically designed to simplify lambda Expressions.
@@ -54,7 +52,7 @@
  *
  * @author Raquel Pau
  */
-public final class MethodReferenceExpr extends Expression implements NodeWithTypeArguments<MethodReferenceExpr>, NodeWithIdentifier<MethodReferenceExpr> {
+public class MethodReferenceExpr extends Expression implements NodeWithTypeArguments<MethodReferenceExpr>, NodeWithIdentifier<MethodReferenceExpr> {
 
     private Expression scope;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Name.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Name.java
index 0eeabd3..d118838 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Name.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/Name.java
@@ -20,27 +20,21 @@
  */
 package com.github.javaparser.ast.expr;
 
-import com.github.javaparser.JavaParser;
+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.nodeTypes.NodeWithAnnotations;
 import com.github.javaparser.ast.nodeTypes.NodeWithIdentifier;
 import com.github.javaparser.ast.observer.ObservableProperty;
-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.NameMetaModel;
 import com.github.javaparser.metamodel.NonEmptyProperty;
-import java.util.Arrays;
-import java.util.List;
+import com.github.javaparser.metamodel.OptionalProperty;
 import java.util.Optional;
 import static com.github.javaparser.utils.Utils.assertNonEmpty;
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import com.github.javaparser.metamodel.OptionalProperty;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A name that may consist of multiple identifiers.
@@ -54,7 +48,7 @@
  * @author Julio Vilmar Gesser
  * @see SimpleName
  */
-public final class Name extends Node implements NodeWithIdentifier<Name>, NodeWithAnnotations<Name> {
+public class Name extends Node implements NodeWithIdentifier<Name> {
 
     @NonEmptyProperty
     private String identifier;
@@ -62,34 +56,27 @@
     @OptionalProperty
     private Name qualifier;
 
-    private NodeList<AnnotationExpr> annotations;
-
     public Name() {
-        this(null, null, "empty", new NodeList<>());
+        this(null, null, "empty");
     }
 
     public Name(final String identifier) {
-        this(null, null, identifier, new NodeList<>());
-    }
-
-    public Name(Name qualifier, final String identifier) {
-        this(null, qualifier, identifier, new NodeList<>());
+        this(null, null, identifier);
     }
 
     @AllFieldsConstructor
-    public Name(Name qualifier, final String identifier, NodeList<AnnotationExpr> annotations) {
-        this(null, qualifier, identifier, annotations);
+    public Name(Name qualifier, final String identifier) {
+        this(null, qualifier, identifier);
     }
 
     /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public Name(TokenRange tokenRange, Name qualifier, String identifier, NodeList<AnnotationExpr> annotations) {
+    public Name(TokenRange tokenRange, Name qualifier, String identifier) {
         super(tokenRange);
         setQualifier(qualifier);
         setIdentifier(identifier);
-        setAnnotations(annotations);
         customInitialization();
     }
 
@@ -122,20 +109,6 @@
     }
 
     /**
-     * Creates a new {@link Name} from a qualified name.<br>
-     * The qualified name can contains "." (dot) characters.
-     *
-     * @param qualifiedName qualified name
-     * @return instanceof {@link Name}
-     * @deprecated use JavaParser.parseName instead
-     */
-    @Deprecated
-    public static Name parse(String qualifiedName) {
-        assertNonEmpty(qualifiedName);
-        return JavaParser.parseName(qualifiedName);
-    }
-
-    /**
      * @return the complete qualified name. Only the identifiers and the dots, so no comments or whitespace.
      */
     public String asString() {
@@ -168,12 +141,6 @@
     public boolean remove(Node node) {
         if (node == null)
             return false;
-        for (int i = 0; i < annotations.size(); i++) {
-            if (annotations.get(i) == node) {
-                annotations.remove(i);
-                return true;
-            }
-        }
         if (qualifier != null) {
             if (node == qualifier) {
                 removeQualifier();
@@ -188,25 +155,6 @@
         return setQualifier((Name) null);
     }
 
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public NodeList<AnnotationExpr> getAnnotations() {
-        return annotations;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Name setAnnotations(final NodeList<AnnotationExpr> annotations) {
-        assertNotNull(annotations);
-        if (annotations == this.annotations) {
-            return (Name) this;
-        }
-        notifyPropertyChange(ObservableProperty.ANNOTATIONS, this.annotations, annotations);
-        if (this.annotations != null)
-            this.annotations.setParentNode(null);
-        this.annotations = annotations;
-        setAsParentNodeOf(annotations);
-        return this;
-    }
-
     @Override
     @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
     public Name clone() {
@@ -224,12 +172,6 @@
     public boolean replace(Node node, Node replacementNode) {
         if (node == null)
             return false;
-        for (int i = 0; i < annotations.size(); i++) {
-            if (annotations.get(i) == node) {
-                annotations.set(i, (AnnotationExpr) replacementNode);
-                return true;
-            }
-        }
         if (qualifier != null) {
             if (node == qualifier) {
                 setQualifier((Name) replacementNode);
@@ -238,4 +180,18 @@
         }
         return super.replace(node, replacementNode);
     }
+
+    /**
+     * A top level name is a name that is not contained in a larger Name instance.
+     */
+    public boolean isTopLevel() {
+        return !isInternal();
+    }
+
+    /**
+     * An internal name is a name that constitutes a part of a larger Name instance.
+     */
+    public boolean isInternal() {
+        return getParentNode().filter(parent -> parent instanceof Name).isPresent();
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NameExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NameExpr.java
index d871589..69191f1 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NameExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NameExpr.java
@@ -23,6 +23,7 @@
 import com.github.javaparser.ast.AllFieldsConstructor;
 import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
 import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import static com.github.javaparser.utils.Utils.assertNotNull;
@@ -30,13 +31,13 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.NameExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.resolution.types.ResolvedUnionType;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Whenever a SimpleName is used in an expression, it is wrapped in NameExpr.
@@ -44,7 +45,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class NameExpr extends Expression implements NodeWithSimpleName<NameExpr>, Resolvable<ResolvedValueDeclaration> {
+public class NameExpr extends Expression implements NodeWithSimpleName<NameExpr>, Resolvable<ResolvedValueDeclaration> {
 
     private SimpleName name;
 
@@ -152,6 +153,18 @@
         action.accept(this);
     }
 
+    /**
+     * Attempts to resolve the declaration corresponding to the accessed name. If successful, a
+     * {@link ResolvedValueDeclaration} representing the declaration of the value accessed by this {@code NameExpr} is
+     * returned. Otherwise, an {@link UnsolvedSymbolException} is thrown.
+     *
+     * @return a {@link ResolvedValueDeclaration} representing the declaration of the accessed value.
+     * @throws UnsolvedSymbolException if the declaration corresponding to the name expression could not be resolved.
+     * @see FieldAccessExpr#resolve()
+     * @see MethodCallExpr#resolve()
+     * @see ObjectCreationExpr#resolve()
+     * @see ExplicitConstructorInvocationStmt#resolve()
+     */
     @Override
     public ResolvedValueDeclaration resolve() {
         return getSymbolResolver().resolveDeclaration(this, ResolvedValueDeclaration.class);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NormalAnnotationExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NormalAnnotationExpr.java
index dd0fce5..7ff90e9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NormalAnnotationExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NormalAnnotationExpr.java
@@ -25,23 +25,21 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 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.NormalAnnotationExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An annotation that has zero or more key-value pairs.<br/><code>@Mapping(a=5, d=10)</code>
  * @author Julio Vilmar Gesser
  */
-public final class NormalAnnotationExpr extends AnnotationExpr {
+public class NormalAnnotationExpr extends AnnotationExpr {
 
     private NodeList<MemberValuePair> pairs;
 
@@ -109,7 +107,7 @@
      *
      * @return this, the {@link NormalAnnotationExpr}
      */
-    public NormalAnnotationExpr addPair(String key, NameExpr value) {
+    public NormalAnnotationExpr addPair(String key, Expression value) {
         MemberValuePair memberValuePair = new MemberValuePair(key, value);
         getPairs().add(memberValuePair);
         return this;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NullLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NullLiteralExpr.java
index b71ed5b..3e3646b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NullLiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/NullLiteralExpr.java
@@ -27,10 +27,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.NullLiteralExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A literal "null".
@@ -38,7 +38,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class NullLiteralExpr extends LiteralExpr {
+public class NullLiteralExpr extends LiteralExpr {
 
     @AllFieldsConstructor
     public NullLiteralExpr() {
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 c4fe045..cce58d9 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
@@ -28,6 +28,7 @@
 import com.github.javaparser.ast.nodeTypes.NodeWithType;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
 import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.ast.visitor.GenericVisitor;
@@ -38,11 +39,13 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ObjectCreationExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
+import com.github.javaparser.resolution.Resolvable;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A constructor call.
@@ -54,7 +57,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ObjectCreationExpr extends Expression implements NodeWithTypeArguments<ObjectCreationExpr>, NodeWithType<ObjectCreationExpr, ClassOrInterfaceType>, NodeWithArguments<ObjectCreationExpr>, NodeWithOptionalScope<ObjectCreationExpr> {
+public class ObjectCreationExpr extends Expression implements NodeWithTypeArguments<ObjectCreationExpr>, NodeWithType<ObjectCreationExpr, ClassOrInterfaceType>, NodeWithArguments<ObjectCreationExpr>, NodeWithOptionalScope<ObjectCreationExpr>, Resolvable<ResolvedConstructorDeclaration> {
 
     @OptionalProperty
     private Expression scope;
@@ -81,7 +84,7 @@
      * @param arguments Any arguments to pass to the constructor
      */
     public ObjectCreationExpr(final Expression scope, final ClassOrInterfaceType type, final NodeList<Expression> arguments) {
-        this(null, scope, type, new NodeList<>(), arguments, null);
+        this(null, scope, type, null, arguments, null);
     }
 
     @AllFieldsConstructor
@@ -343,7 +346,21 @@
         action.accept(this);
     }
 
-    public ResolvedConstructorDeclaration resolveInvokedConstructor() {
+    /**
+     * Attempts to resolve the declaration corresponding to the invoked constructor. If successful, a
+     * {@link ResolvedConstructorDeclaration} representing the declaration of the constructor invoked by this
+     * {@code ObjectCreationExpr} is returned. Otherwise, an {@link UnsolvedSymbolException} is thrown.
+     *
+     * @return a {@link ResolvedConstructorDeclaration} representing the declaration of the invoked constructor.
+     * @throws UnsolvedSymbolException if the declaration corresponding to the object creation expression could not be
+     *                                 resolved.
+     * @see NameExpr#resolve()
+     * @see FieldAccessExpr#resolve()
+     * @see MethodCallExpr#resolve()
+     * @see ExplicitConstructorInvocationStmt#resolve()
+     */
+    @Override
+    public ResolvedConstructorDeclaration resolve() {
         return getSymbolResolver().resolveDeclaration(this, ResolvedConstructorDeclaration.class);
     }
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SimpleName.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SimpleName.java
index faaa541..6caed2a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SimpleName.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SimpleName.java
@@ -31,8 +31,8 @@
 import com.github.javaparser.metamodel.NonEmptyProperty;
 import com.github.javaparser.metamodel.SimpleNameMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A name that consists of a single identifier.
@@ -40,7 +40,7 @@
  *
  * @see Name
  */
-public final class SimpleName extends Node implements NodeWithIdentifier<SimpleName> {
+public class SimpleName extends Node implements NodeWithIdentifier<SimpleName> {
 
     @NonEmptyProperty
     private String identifier;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SingleMemberAnnotationExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SingleMemberAnnotationExpr.java
index 679c714..ca2bcfc 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SingleMemberAnnotationExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SingleMemberAnnotationExpr.java
@@ -29,17 +29,17 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.SingleMemberAnnotationExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An annotation that has a single value. <br/><code>@Count(15)</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class SingleMemberAnnotationExpr extends AnnotationExpr {
+public class SingleMemberAnnotationExpr extends AnnotationExpr {
 
     private Expression memberValue;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/StringLiteralExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/StringLiteralExpr.java
index a7b4dd5..37689b1 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/StringLiteralExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/StringLiteralExpr.java
@@ -29,10 +29,10 @@
 import com.github.javaparser.metamodel.StringLiteralExprMetaModel;
 import com.github.javaparser.utils.StringEscapeUtils;
 import com.github.javaparser.utils.Utils;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A literal string.
@@ -44,7 +44,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class StringLiteralExpr extends LiteralStringValueExpr {
+public class StringLiteralExpr extends LiteralStringValueExpr {
 
     public StringLiteralExpr() {
         this(null, "empty");
@@ -61,16 +61,6 @@
     }
 
     /**
-     * Utility method that creates a new StringLiteralExpr. Escapes EOL characters.
-     *
-     * @deprecated Use {@link #StringLiteralExpr(String)} instead.
-     */
-    @Deprecated
-    public static StringLiteralExpr escape(String string) {
-        return new StringLiteralExpr(Utils.escapeEndOfLines(string));
-    }
-
-    /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SuperExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SuperExpr.java
index 2de37fb..b64c110 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SuperExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SuperExpr.java
@@ -30,40 +30,42 @@
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.metamodel.SuperExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
- * An occurrence of the "super" keyword. <br/><code>World.super.greet()</code> is a MethodCallExpr of method name greet,
- * and scope "World.super" which is a SuperExpr with classExpr "World". <br/><code>super.name</code> is a
- * FieldAccessExpr of field greet, and a SuperExpr as its scope. The SuperExpr has no classExpr.
+ * An occurrence of the "super" keyword. <br/>
+ * <code>World.super.greet()</code> is a MethodCallExpr of method name greet,
+ * and scope "World.super" which is a SuperExpr with typeName "World". <br/>
+ * <code>super.name</code> is a FieldAccessExpr of field greet, and a SuperExpr as its scope.
+ * This SuperExpr has no typeName.
  *
  * @author Julio Vilmar Gesser
  * @see com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt
  * @see ThisExpr
  */
-public final class SuperExpr extends Expression {
+public class SuperExpr extends Expression {
 
     @OptionalProperty
-    private Expression classExpr;
+    private Name typeName;
 
     public SuperExpr() {
         this(null, null);
     }
 
     @AllFieldsConstructor
-    public SuperExpr(final Expression classExpr) {
-        this(null, classExpr);
+    public SuperExpr(final Name typeName) {
+        this(null, typeName);
     }
 
     /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public SuperExpr(TokenRange tokenRange, Expression classExpr) {
+    public SuperExpr(TokenRange tokenRange, Name typeName) {
         super(tokenRange);
-        setClassExpr(classExpr);
+        setTypeName(typeName);
         customInitialization();
     }
 
@@ -80,26 +82,20 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Optional<Expression> getClassExpr() {
-        return Optional.ofNullable(classExpr);
+    public Optional<Name> getTypeName() {
+        return Optional.ofNullable(typeName);
     }
 
-    /**
-     * Sets the classExpr
-     *
-     * @param classExpr the classExpr, can be null
-     * @return this, the SuperExpr
-     */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public SuperExpr setClassExpr(final Expression classExpr) {
-        if (classExpr == this.classExpr) {
+    public SuperExpr setTypeName(final Name typeName) {
+        if (typeName == this.typeName) {
             return (SuperExpr) this;
         }
-        notifyPropertyChange(ObservableProperty.CLASS_EXPR, this.classExpr, classExpr);
-        if (this.classExpr != null)
-            this.classExpr.setParentNode(null);
-        this.classExpr = classExpr;
-        setAsParentNodeOf(classExpr);
+        notifyPropertyChange(ObservableProperty.TYPE_NAME, this.typeName, typeName);
+        if (this.typeName != null)
+            this.typeName.setParentNode(null);
+        this.typeName = typeName;
+        setAsParentNodeOf(typeName);
         return this;
     }
 
@@ -108,20 +104,15 @@
     public boolean remove(Node node) {
         if (node == null)
             return false;
-        if (classExpr != null) {
-            if (node == classExpr) {
-                removeClassExpr();
+        if (typeName != null) {
+            if (node == typeName) {
+                removeTypeName();
                 return true;
             }
         }
         return super.remove(node);
     }
 
-    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public SuperExpr removeClassExpr() {
-        return setClassExpr((Expression) null);
-    }
-
     @Override
     @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
     public SuperExpr clone() {
@@ -135,20 +126,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        if (classExpr != null) {
-            if (node == classExpr) {
-                setClassExpr((Expression) replacementNode);
-                return true;
-            }
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public boolean isSuperExpr() {
         return true;
@@ -170,4 +147,28 @@
     public Optional<SuperExpr> toSuperExpr() {
         return Optional.of(this);
     }
+
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public SuperExpr removeClassName() {
+        return setTypeName((Name) null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        if (typeName != null) {
+            if (node == typeName) {
+                setTypeName((Name) replacementNode);
+                return true;
+            }
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public SuperExpr removeTypeName() {
+        return setTypeName((Name) null);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SwitchExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SwitchExpr.java
new file mode 100644
index 0000000..2d5ba02
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/SwitchExpr.java
@@ -0,0 +1,202 @@
+/*
+ * 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.expr;
+
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Generated;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.nodeTypes.SwitchNode;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.stmt.SwitchEntry;
+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.SwitchExprMetaModel;
+import java.util.Optional;
+import java.util.function.Consumer;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+
+/**
+ * <h1>The switch expression</h1>
+ * <h2>Java 1.0-11</h2>
+ * Not available.
+ * <h2>Java 12-</h2>
+ * Like {@link com.github.javaparser.ast.stmt.SwitchStmt},
+ * but can also be used as an expression.
+ * <br/>
+ * <br/><code>int a = switch(x) { case 5,6 -> 20; case 9 -> 30; default -> 40; };</code>
+ * <br/><code>int a = switch(x) { case 5,6: break 20; default: break 5+5; };</code>
+ *
+ * @author Julio Vilmar Gesser
+ * @see SwitchEntry
+ * @see com.github.javaparser.ast.stmt.SwitchStmt
+ * @see SwitchNode
+ */
+public class SwitchExpr extends Expression implements SwitchNode {
+
+    private Expression selector;
+
+    private NodeList<SwitchEntry> entries;
+
+    public SwitchExpr() {
+        this(null, new NameExpr(), new NodeList<>());
+    }
+
+    @AllFieldsConstructor
+    public SwitchExpr(final Expression selector, final NodeList<SwitchEntry> entries) {
+        this(null, selector, entries);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public SwitchExpr(TokenRange tokenRange, Expression selector, NodeList<SwitchEntry> entries) {
+        super(tokenRange);
+        setSelector(selector);
+        setEntries(entries);
+        customInitialization();
+    }
+
+    @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);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public NodeList<SwitchEntry> getEntries() {
+        return entries;
+    }
+
+    public SwitchEntry getEntry(int i) {
+        return getEntries().get(i);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Expression getSelector() {
+        return selector;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public SwitchExpr setEntries(final NodeList<SwitchEntry> entries) {
+        assertNotNull(entries);
+        if (entries == this.entries) {
+            return (SwitchExpr) this;
+        }
+        notifyPropertyChange(ObservableProperty.ENTRIES, this.entries, entries);
+        if (this.entries != null)
+            this.entries.setParentNode(null);
+        this.entries = entries;
+        setAsParentNodeOf(entries);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public SwitchExpr setSelector(final Expression selector) {
+        assertNotNull(selector);
+        if (selector == this.selector) {
+            return (SwitchExpr) this;
+        }
+        notifyPropertyChange(ObservableProperty.SELECTOR, this.selector, selector);
+        if (this.selector != null)
+            this.selector.setParentNode(null);
+        this.selector = selector;
+        setAsParentNodeOf(selector);
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < entries.size(); i++) {
+            if (entries.get(i) == node) {
+                entries.remove(i);
+                return true;
+            }
+        }
+        return super.remove(node);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public SwitchExpr clone() {
+        return (SwitchExpr) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < entries.size(); i++) {
+            if (entries.get(i) == node) {
+                entries.set(i, (SwitchEntry) replacementNode);
+                return true;
+            }
+        }
+        if (node == selector) {
+            setSelector((Expression) replacementNode);
+            return true;
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isSwitchExpr() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public SwitchExpr asSwitchExpr() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<SwitchExpr> toSwitchExpr() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifSwitchExpr(Consumer<SwitchExpr> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public SwitchExprMetaModel getMetaModel() {
+        return JavaParserMetaModel.switchExprMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ThisExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ThisExpr.java
index dc9981d..d596217 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ThisExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/ThisExpr.java
@@ -21,7 +21,6 @@
 package com.github.javaparser.ast.expr;
 
 import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.body.TypeDeclaration;
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
@@ -31,43 +30,44 @@
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.metamodel.ThisExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
-import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
- * An occurrence of the "this" keyword. <br/><code>World.this.greet()</code> is a MethodCallExpr of method name greet,
- * and scope "World.super" which is a ThisExpr with classExpr "World". <br/><code>this.name</code> is a
- * FieldAccessExpr of field greet, and a ThisExpr as its scope. The ThisExpr has no classExpr.
+ * An occurrence of the "this" keyword. <br/>
+ * <code>World.this.greet()</code> is a MethodCallExpr of method name greet,
+ * and scope "World.this" which is a ThisExpr with typeName "World". <br/>
+ * <code>this.name</code> is a FieldAccessExpr of field greet, and a ThisExpr as its scope.
+ * This ThisExpr has no typeName.
  *
  * @author Julio Vilmar Gesser
  * @see com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt
- * @see ThisExpr
+ * @see SuperExpr
  */
-public final class ThisExpr extends Expression implements Resolvable<ResolvedTypeDeclaration> {
+public class ThisExpr extends Expression implements Resolvable<ResolvedTypeDeclaration> {
 
     @OptionalProperty
-    private Expression classExpr;
+    private Name typeName;
 
     public ThisExpr() {
         this(null, null);
     }
 
     @AllFieldsConstructor
-    public ThisExpr(final Expression classExpr) {
-        this(null, classExpr);
+    public ThisExpr(final Name typeName) {
+        this(null, typeName);
     }
 
     /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ThisExpr(TokenRange tokenRange, Expression classExpr) {
+    public ThisExpr(TokenRange tokenRange, Name typeName) {
         super(tokenRange);
-        setClassExpr(classExpr);
+        setTypeName(typeName);
         customInitialization();
     }
 
@@ -84,20 +84,20 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Optional<Expression> getClassExpr() {
-        return Optional.ofNullable(classExpr);
+    public Optional<Name> getTypeName() {
+        return Optional.ofNullable(typeName);
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ThisExpr setClassExpr(final Expression classExpr) {
-        if (classExpr == this.classExpr) {
+    public ThisExpr setTypeName(final Name typeName) {
+        if (typeName == this.typeName) {
             return (ThisExpr) this;
         }
-        notifyPropertyChange(ObservableProperty.CLASS_EXPR, this.classExpr, classExpr);
-        if (this.classExpr != null)
-            this.classExpr.setParentNode(null);
-        this.classExpr = classExpr;
-        setAsParentNodeOf(classExpr);
+        notifyPropertyChange(ObservableProperty.TYPE_NAME, this.typeName, typeName);
+        if (this.typeName != null)
+            this.typeName.setParentNode(null);
+        this.typeName = typeName;
+        setAsParentNodeOf(typeName);
         return this;
     }
 
@@ -106,9 +106,9 @@
     public boolean remove(Node node) {
         if (node == null)
             return false;
-        if (classExpr != null) {
-            if (node == classExpr) {
-                removeClassExpr();
+        if (typeName != null) {
+            if (node == typeName) {
+                removeTypeName();
                 return true;
             }
         }
@@ -116,8 +116,8 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public ThisExpr removeClassExpr() {
-        return setClassExpr((Expression) null);
+    public ThisExpr removeClassName() {
+        return setTypeName((Name) null);
     }
 
     @Override
@@ -137,9 +137,9 @@
     public boolean replace(Node node, Node replacementNode) {
         if (node == null)
             return false;
-        if (classExpr != null) {
-            if (node == classExpr) {
-                setClassExpr((Expression) replacementNode);
+        if (typeName != null) {
+            if (node == typeName) {
+                setTypeName((Name) replacementNode);
                 return true;
             }
         }
@@ -173,4 +173,9 @@
     public Optional<ThisExpr> toThisExpr() {
         return Optional.of(this);
     }
+
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public ThisExpr removeTypeName() {
+        return setTypeName((Name) null);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/TypeExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/TypeExpr.java
index 3d74b6e..ff430c9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/TypeExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/TypeExpr.java
@@ -32,10 +32,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.TypeExprMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * This class is just instantiated as scopes for MethodReferenceExpr nodes to encapsulate Types.
@@ -44,7 +44,7 @@
  *
  * @author Raquel Pau
  */
-public final class TypeExpr extends Expression implements NodeWithType<TypeExpr, Type> {
+public class TypeExpr extends Expression implements NodeWithType<TypeExpr, Type> {
 
     private Type type;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/UnaryExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/UnaryExpr.java
index 4008544..4655ea6 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/UnaryExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/UnaryExpr.java
@@ -32,14 +32,14 @@
 import com.github.javaparser.metamodel.UnaryExprMetaModel;
 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;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An expression where an operator is applied to a single expression.
- * It supports the operators that are found the the UnaryExpr.Operator enum.
+ * It supports the operators that are found in the UnaryExpr.Operator enum.
  * <br/><code>11++</code>
  * <br/><code>++11</code>
  * <br/><code>~1</code>
@@ -47,7 +47,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class UnaryExpr extends Expression implements NodeWithExpression<UnaryExpr> {
+public class UnaryExpr extends Expression implements NodeWithExpression<UnaryExpr> {
 
     public enum Operator implements Printable {
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/VariableDeclarationExpr.java b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/VariableDeclarationExpr.java
index 8745ce7..06e896b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/expr/VariableDeclarationExpr.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/expr/VariableDeclarationExpr.java
@@ -37,15 +37,13 @@
 import com.github.javaparser.metamodel.NonEmptyProperty;
 import com.github.javaparser.metamodel.VariableDeclarationExprMetaModel;
 import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.List;
 import java.util.stream.Collectors;
 import static com.github.javaparser.ast.NodeList.nodeList;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A declaration of variables.
@@ -58,9 +56,9 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class VariableDeclarationExpr extends Expression implements NodeWithFinalModifier<VariableDeclarationExpr>, NodeWithAnnotations<VariableDeclarationExpr>, NodeWithVariables<VariableDeclarationExpr> {
+public class VariableDeclarationExpr extends Expression implements NodeWithFinalModifier<VariableDeclarationExpr>, NodeWithAnnotations<VariableDeclarationExpr>, NodeWithVariables<VariableDeclarationExpr> {
 
-    private EnumSet<Modifier> modifiers;
+    private NodeList<Modifier> modifiers;
 
     private NodeList<AnnotationExpr> annotations;
 
@@ -68,35 +66,35 @@
     private NodeList<VariableDeclarator> variables;
 
     public VariableDeclarationExpr() {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), new NodeList<>());
+        this(null, new NodeList<>(), new NodeList<>(), new NodeList<>());
     }
 
     public VariableDeclarationExpr(final Type type, String variableName) {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), nodeList(new VariableDeclarator(type, variableName)));
+        this(null, new NodeList<>(), new NodeList<>(), nodeList(new VariableDeclarator(type, variableName)));
     }
 
     public VariableDeclarationExpr(VariableDeclarator var) {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), nodeList(var));
+        this(null, new NodeList<>(), new NodeList<>(), nodeList(var));
     }
 
     public VariableDeclarationExpr(final Type type, String variableName, Modifier... modifiers) {
-        this(null, Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), new NodeList<>(), nodeList(new VariableDeclarator(type, variableName)));
+        this(null, Arrays.stream(modifiers).collect(Collectors.toCollection(() -> new NodeList<>())), new NodeList<>(), nodeList(new VariableDeclarator(type, variableName)));
     }
 
     public VariableDeclarationExpr(VariableDeclarator var, Modifier... modifiers) {
-        this(null, Arrays.stream(modifiers).collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), new NodeList<>(), nodeList(var));
+        this(null, Arrays.stream(modifiers).collect(Collectors.toCollection(() -> new NodeList<>())), new NodeList<>(), nodeList(var));
     }
 
     public VariableDeclarationExpr(final NodeList<VariableDeclarator> variables) {
-        this(null, EnumSet.noneOf(Modifier.class), new NodeList<>(), variables);
+        this(null, new NodeList<>(), new NodeList<>(), variables);
     }
 
-    public VariableDeclarationExpr(final EnumSet<Modifier> modifiers, final NodeList<VariableDeclarator> variables) {
+    public VariableDeclarationExpr(final NodeList<Modifier> modifiers, final NodeList<VariableDeclarator> variables) {
         this(null, modifiers, new NodeList<>(), variables);
     }
 
     @AllFieldsConstructor
-    public VariableDeclarationExpr(final EnumSet<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final NodeList<VariableDeclarator> variables) {
+    public VariableDeclarationExpr(final NodeList<Modifier> modifiers, final NodeList<AnnotationExpr> annotations, final NodeList<VariableDeclarator> variables) {
         this(null, modifiers, annotations, variables);
     }
 
@@ -104,7 +102,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public VariableDeclarationExpr(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) {
+    public VariableDeclarationExpr(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) {
         super(tokenRange);
         setModifiers(modifiers);
         setAnnotations(annotations);
@@ -136,7 +134,7 @@
      * @see Modifier
      */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public EnumSet<Modifier> getModifiers() {
+    public NodeList<Modifier> getModifiers() {
         return modifiers;
     }
 
@@ -160,13 +158,16 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public VariableDeclarationExpr setModifiers(final EnumSet<Modifier> modifiers) {
+    public VariableDeclarationExpr setModifiers(final NodeList<Modifier> modifiers) {
         assertNotNull(modifiers);
         if (modifiers == this.modifiers) {
             return (VariableDeclarationExpr) this;
         }
         notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
+        if (this.modifiers != null)
+            this.modifiers.setParentNode(null);
         this.modifiers = modifiers;
+        setAsParentNodeOf(modifiers);
         return this;
     }
 
@@ -195,6 +196,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.remove(i);
+                return true;
+            }
+        }
         for (int i = 0; i < variables.size(); i++) {
             if (variables.get(i) == node) {
                 variables.remove(i);
@@ -227,6 +234,12 @@
                 return true;
             }
         }
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.set(i, (Modifier) replacementNode);
+                return true;
+            }
+        }
         for (int i = 0; i < variables.size(); i++) {
             if (variables.get(i) == node) {
                 variables.set(i, (VariableDeclarator) replacementNode);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleDeclaration.java
index 547c2cc..3202f31 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleDeclaration.java
@@ -13,16 +13,15 @@
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.ModuleDeclarationMetaModel;
-import java.util.Arrays;
-import java.util.List;
+import static com.github.javaparser.StaticJavaParser.parseModuleDirective;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A Java 9 Jigsaw module declaration. <code>@Foo module com.github.abc { requires a.B; }</code>
  */
-public final class ModuleDeclaration extends Node implements NodeWithName<ModuleDeclaration>, NodeWithAnnotations<ModuleDeclaration> {
+public class ModuleDeclaration extends Node implements NodeWithName<ModuleDeclaration>, NodeWithAnnotations<ModuleDeclaration> {
 
     private Name name;
 
@@ -30,7 +29,7 @@
 
     private boolean isOpen;
 
-    private NodeList<ModuleStmt> moduleStmts;
+    private NodeList<ModuleDirective> directives;
 
     public ModuleDeclaration() {
         this(null, new NodeList<>(), new Name(), false, new NodeList<>());
@@ -41,20 +40,20 @@
     }
 
     @AllFieldsConstructor
-    public ModuleDeclaration(NodeList<AnnotationExpr> annotations, Name name, boolean isOpen, NodeList<ModuleStmt> moduleStmts) {
-        this(null, annotations, name, isOpen, moduleStmts);
+    public ModuleDeclaration(NodeList<AnnotationExpr> annotations, Name name, boolean isOpen, NodeList<ModuleDirective> directives) {
+        this(null, annotations, name, isOpen, directives);
     }
 
     /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ModuleDeclaration(TokenRange tokenRange, NodeList<AnnotationExpr> annotations, Name name, boolean isOpen, NodeList<ModuleStmt> moduleStmts) {
+    public ModuleDeclaration(TokenRange tokenRange, NodeList<AnnotationExpr> annotations, Name name, boolean isOpen, NodeList<ModuleDirective> directives) {
         super(tokenRange);
         setAnnotations(annotations);
         setName(name);
         setOpen(isOpen);
-        setModuleStmts(moduleStmts);
+        setDirectives(directives);
         customInitialization();
     }
 
@@ -119,9 +118,9 @@
                 return true;
             }
         }
-        for (int i = 0; i < moduleStmts.size(); i++) {
-            if (moduleStmts.get(i) == node) {
-                moduleStmts.remove(i);
+        for (int i = 0; i < directives.size(); i++) {
+            if (directives.get(i) == node) {
+                directives.remove(i);
                 return true;
             }
         }
@@ -144,21 +143,21 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public NodeList<ModuleStmt> getModuleStmts() {
-        return moduleStmts;
+    public NodeList<ModuleDirective> getDirectives() {
+        return directives;
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleDeclaration setModuleStmts(final NodeList<ModuleStmt> moduleStmts) {
-        assertNotNull(moduleStmts);
-        if (moduleStmts == this.moduleStmts) {
+    public ModuleDeclaration setDirectives(final NodeList<ModuleDirective> directives) {
+        assertNotNull(directives);
+        if (directives == this.directives) {
             return (ModuleDeclaration) this;
         }
-        notifyPropertyChange(ObservableProperty.MODULE_STMTS, this.moduleStmts, moduleStmts);
-        if (this.moduleStmts != null)
-            this.moduleStmts.setParentNode(null);
-        this.moduleStmts = moduleStmts;
-        setAsParentNodeOf(moduleStmts);
+        notifyPropertyChange(ObservableProperty.DIRECTIVES, this.directives, directives);
+        if (this.directives != null)
+            this.directives.setParentNode(null);
+        this.directives = directives;
+        setAsParentNodeOf(directives);
         return this;
     }
 
@@ -185,9 +184,9 @@
                 return true;
             }
         }
-        for (int i = 0; i < moduleStmts.size(); i++) {
-            if (moduleStmts.get(i) == node) {
-                moduleStmts.set(i, (ModuleStmt) replacementNode);
+        for (int i = 0; i < directives.size(); i++) {
+            if (directives.get(i) == node) {
+                directives.set(i, (ModuleDirective) replacementNode);
                 return true;
             }
         }
@@ -197,4 +196,16 @@
         }
         return super.replace(node, replacementNode);
     }
+
+    /**
+     * Add a directive to the module, like "exports R.S to T1.U1, T2.U2;"
+     */
+    public ModuleDeclaration addDirective(String directive) {
+        return addDirective(parseModuleDirective(directive));
+    }
+
+    public ModuleDeclaration addDirective(ModuleDirective directive) {
+        getDirectives().add(directive);
+        return this;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleDirective.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleDirective.java
new file mode 100644
index 0000000..315a4aa
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleDirective.java
@@ -0,0 +1,250 @@
+package com.github.javaparser.ast.modules;
+
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Generated;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.TokenRange;
+import java.util.function.Consumer;
+import static com.github.javaparser.utils.CodeGenerationUtils.f;
+import java.util.Optional;
+import com.github.javaparser.metamodel.ModuleDirectiveMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+
+/**
+ * A module directive.
+ */
+public abstract class ModuleDirective extends Node {
+
+    @AllFieldsConstructor
+    public ModuleDirective() {
+        this(null);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public ModuleDirective(TokenRange tokenRange) {
+        super(tokenRange);
+        customInitialization();
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        return super.remove(node);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public ModuleDirective clone() {
+        return (ModuleDirective) accept(new CloneVisitor(), null);
+    }
+
+    @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);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleExportsStmt() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleExportsDirective asModuleExportsStmt() {
+        throw new IllegalStateException(f("%s is not an ModuleExportsDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleOpensStmt() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleOpensDirective asModuleOpensStmt() {
+        throw new IllegalStateException(f("%s is not an ModuleOpensDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleProvidesStmt() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleProvidesDirective asModuleProvidesStmt() {
+        throw new IllegalStateException(f("%s is not an ModuleProvidesDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleRequiresStmt() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleRequiresDirective asModuleRequiresStmt() {
+        throw new IllegalStateException(f("%s is not an ModuleRequiresDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleUsesStmt() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleUsesDirective asModuleUsesStmt() {
+        throw new IllegalStateException(f("%s is not an ModuleUsesDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleExportsStmt(Consumer<ModuleExportsDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleOpensStmt(Consumer<ModuleOpensDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleProvidesStmt(Consumer<ModuleProvidesDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleRequiresStmt(Consumer<ModuleRequiresDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleUsesStmt(Consumer<ModuleUsesDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleExportsDirective> toModuleExportsStmt() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleOpensDirective> toModuleOpensStmt() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleProvidesDirective> toModuleProvidesStmt() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleRequiresDirective> toModuleRequiresStmt() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleUsesDirective> toModuleUsesStmt() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleExportsDirective() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleExportsDirective asModuleExportsDirective() {
+        throw new IllegalStateException(f("%s is not an ModuleExportsDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleExportsDirective> toModuleExportsDirective() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleExportsDirective(Consumer<ModuleExportsDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleOpensDirective() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleOpensDirective asModuleOpensDirective() {
+        throw new IllegalStateException(f("%s is not an ModuleOpensDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleOpensDirective> toModuleOpensDirective() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleOpensDirective(Consumer<ModuleOpensDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleProvidesDirective() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleProvidesDirective asModuleProvidesDirective() {
+        throw new IllegalStateException(f("%s is not an ModuleProvidesDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleProvidesDirective> toModuleProvidesDirective() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleProvidesDirective(Consumer<ModuleProvidesDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleRequiresDirective() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleRequiresDirective asModuleRequiresDirective() {
+        throw new IllegalStateException(f("%s is not an ModuleRequiresDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleRequiresDirective> toModuleRequiresDirective() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleRequiresDirective(Consumer<ModuleRequiresDirective> action) {
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleUsesDirective() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleUsesDirective asModuleUsesDirective() {
+        throw new IllegalStateException(f("%s is not an ModuleUsesDirective", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleUsesDirective> toModuleUsesDirective() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleUsesDirective(Consumer<ModuleUsesDirective> action) {
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ModuleDirectiveMetaModel getMetaModel() {
+        return JavaParserMetaModel.moduleDirectiveMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleExportsDirective.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleExportsDirective.java
new file mode 100644
index 0000000..2996dd2
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleExportsDirective.java
@@ -0,0 +1,194 @@
+package com.github.javaparser.ast.modules;
+
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.nodeTypes.NodeWithName;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.ast.visitor.GenericVisitor;
+import com.github.javaparser.ast.visitor.VoidVisitor;
+import static com.github.javaparser.StaticJavaParser.parseName;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.TokenRange;
+import java.util.function.Consumer;
+import java.util.Optional;
+import com.github.javaparser.metamodel.ModuleExportsDirectiveMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.ast.Generated;
+
+/**
+ * An exports directive in module-info.java. <code>exports R.S to T1.U1, T2.U2;</code>
+ */
+public class ModuleExportsDirective extends ModuleDirective implements NodeWithName<ModuleExportsDirective> {
+
+    private Name name;
+
+    private NodeList<Name> moduleNames;
+
+    public ModuleExportsDirective() {
+        this(null, new Name(), new NodeList<>());
+    }
+
+    @AllFieldsConstructor
+    public ModuleExportsDirective(Name name, NodeList<Name> moduleNames) {
+        this(null, name, moduleNames);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public ModuleExportsDirective(TokenRange tokenRange, Name name, NodeList<Name> moduleNames) {
+        super(tokenRange);
+        setName(name);
+        setModuleNames(moduleNames);
+        customInitialization();
+    }
+
+    @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.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < moduleNames.size(); i++) {
+            if (moduleNames.get(i) == node) {
+                moduleNames.remove(i);
+                return true;
+            }
+        }
+        return super.remove(node);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Name getName() {
+        return name;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleExportsDirective setName(final Name name) {
+        assertNotNull(name);
+        if (name == this.name) {
+            return (ModuleExportsDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
+        if (this.name != null)
+            this.name.setParentNode(null);
+        this.name = name;
+        setAsParentNodeOf(name);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public NodeList<Name> getModuleNames() {
+        return moduleNames;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleExportsDirective setModuleNames(final NodeList<Name> moduleNames) {
+        assertNotNull(moduleNames);
+        if (moduleNames == this.moduleNames) {
+            return (ModuleExportsDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.MODULE_NAMES, this.moduleNames, moduleNames);
+        if (this.moduleNames != null)
+            this.moduleNames.setParentNode(null);
+        this.moduleNames = moduleNames;
+        setAsParentNodeOf(moduleNames);
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public ModuleExportsDirective clone() {
+        return (ModuleExportsDirective) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < moduleNames.size(); i++) {
+            if (moduleNames.get(i) == node) {
+                moduleNames.set(i, (Name) replacementNode);
+                return true;
+            }
+        }
+        if (node == name) {
+            setName((Name) replacementNode);
+            return true;
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleExportsStmt() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleExportsDirective asModuleExportsStmt() {
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleExportsStmt(Consumer<ModuleExportsDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleExportsDirective> toModuleExportsStmt() {
+        return Optional.of(this);
+    }
+
+    public ModuleExportsDirective addModuleName(String name) {
+        moduleNames.add(parseName(name));
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleExportsDirective() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleExportsDirective asModuleExportsDirective() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleExportsDirective> toModuleExportsDirective() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleExportsDirective(Consumer<ModuleExportsDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ModuleExportsDirectiveMetaModel getMetaModel() {
+        return JavaParserMetaModel.moduleExportsDirectiveMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleExportsStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleExportsStmt.java
deleted file mode 100644
index 61440b1..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleExportsStmt.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package com.github.javaparser.ast.modules;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.nodeTypes.NodeWithName;
-import com.github.javaparser.ast.observer.ObservableProperty;
-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.ModuleExportsStmtMetaModel;
-import java.util.Arrays;
-import java.util.List;
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-import java.util.Optional;
-
-public final class ModuleExportsStmt extends ModuleStmt implements NodeWithName<ModuleExportsStmt> {
-
-    private Name name;
-
-    private NodeList<Name> moduleNames;
-
-    public ModuleExportsStmt() {
-        this(null, new Name(), new NodeList<>());
-    }
-
-    @AllFieldsConstructor
-    public ModuleExportsStmt(Name name, NodeList<Name> moduleNames) {
-        this(null, name, moduleNames);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ModuleExportsStmt(TokenRange tokenRange, Name name, NodeList<Name> moduleNames) {
-        super(tokenRange);
-        setName(name);
-        setModuleNames(moduleNames);
-        customInitialization();
-    }
-
-    @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.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        for (int i = 0; i < moduleNames.size(); i++) {
-            if (moduleNames.get(i) == node) {
-                moduleNames.remove(i);
-                return true;
-            }
-        }
-        return super.remove(node);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Name getName() {
-        return name;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleExportsStmt setName(final Name name) {
-        assertNotNull(name);
-        if (name == this.name) {
-            return (ModuleExportsStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
-        if (this.name != null)
-            this.name.setParentNode(null);
-        this.name = name;
-        setAsParentNodeOf(name);
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public NodeList<Name> getModuleNames() {
-        return moduleNames;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleExportsStmt setModuleNames(final NodeList<Name> moduleNames) {
-        assertNotNull(moduleNames);
-        if (moduleNames == this.moduleNames) {
-            return (ModuleExportsStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.MODULE_NAMES, this.moduleNames, moduleNames);
-        if (this.moduleNames != null)
-            this.moduleNames.setParentNode(null);
-        this.moduleNames = moduleNames;
-        setAsParentNodeOf(moduleNames);
-        return this;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public ModuleExportsStmt clone() {
-        return (ModuleExportsStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public ModuleExportsStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.moduleExportsStmtMetaModel;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        for (int i = 0; i < moduleNames.size(); i++) {
-            if (moduleNames.get(i) == node) {
-                moduleNames.set(i, (Name) replacementNode);
-                return true;
-            }
-        }
-        if (node == name) {
-            setName((Name) replacementNode);
-            return true;
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleExportsStmt() {
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleExportsStmt asModuleExportsStmt() {
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleExportsStmt(Consumer<ModuleExportsStmt> action) {
-        action.accept(this);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleExportsStmt> toModuleExportsStmt() {
-        return Optional.of(this);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleOpensDirective.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleOpensDirective.java
new file mode 100644
index 0000000..a991fc6
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleOpensDirective.java
@@ -0,0 +1,188 @@
+package com.github.javaparser.ast.modules;
+
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.nodeTypes.NodeWithName;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+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.TokenRange;
+import java.util.function.Consumer;
+import java.util.Optional;
+import com.github.javaparser.metamodel.ModuleOpensDirectiveMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.ast.Generated;
+
+/**
+ * An opens directive in module-info.java. <code>opens R.S to T1.U1, T2.U2;</code>
+ */
+public class ModuleOpensDirective extends ModuleDirective implements NodeWithName<ModuleOpensDirective> {
+
+    private Name name;
+
+    private NodeList<Name> moduleNames;
+
+    public ModuleOpensDirective() {
+        this(null, new Name(), new NodeList<>());
+    }
+
+    @AllFieldsConstructor
+    public ModuleOpensDirective(Name name, NodeList<Name> moduleNames) {
+        this(null, name, moduleNames);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public ModuleOpensDirective(TokenRange tokenRange, Name name, NodeList<Name> moduleNames) {
+        super(tokenRange);
+        setName(name);
+        setModuleNames(moduleNames);
+        customInitialization();
+    }
+
+    @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.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < moduleNames.size(); i++) {
+            if (moduleNames.get(i) == node) {
+                moduleNames.remove(i);
+                return true;
+            }
+        }
+        return super.remove(node);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Name getName() {
+        return name;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleOpensDirective setName(final Name name) {
+        assertNotNull(name);
+        if (name == this.name) {
+            return (ModuleOpensDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
+        if (this.name != null)
+            this.name.setParentNode(null);
+        this.name = name;
+        setAsParentNodeOf(name);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public NodeList<Name> getModuleNames() {
+        return moduleNames;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleOpensDirective setModuleNames(final NodeList<Name> moduleNames) {
+        assertNotNull(moduleNames);
+        if (moduleNames == this.moduleNames) {
+            return (ModuleOpensDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.MODULE_NAMES, this.moduleNames, moduleNames);
+        if (this.moduleNames != null)
+            this.moduleNames.setParentNode(null);
+        this.moduleNames = moduleNames;
+        setAsParentNodeOf(moduleNames);
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public ModuleOpensDirective clone() {
+        return (ModuleOpensDirective) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < moduleNames.size(); i++) {
+            if (moduleNames.get(i) == node) {
+                moduleNames.set(i, (Name) replacementNode);
+                return true;
+            }
+        }
+        if (node == name) {
+            setName((Name) replacementNode);
+            return true;
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleOpensStmt() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleOpensDirective asModuleOpensStmt() {
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleOpensStmt(Consumer<ModuleOpensDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleOpensDirective> toModuleOpensStmt() {
+        return Optional.of(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleOpensDirective() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleOpensDirective asModuleOpensDirective() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleOpensDirective> toModuleOpensDirective() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleOpensDirective(Consumer<ModuleOpensDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ModuleOpensDirectiveMetaModel getMetaModel() {
+        return JavaParserMetaModel.moduleOpensDirectiveMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleOpensStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleOpensStmt.java
deleted file mode 100644
index 25565da..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleOpensStmt.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package com.github.javaparser.ast.modules;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.nodeTypes.NodeWithName;
-import com.github.javaparser.ast.observer.ObservableProperty;
-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.ModuleOpensStmtMetaModel;
-import java.util.Arrays;
-import java.util.List;
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-import java.util.Optional;
-
-public final class ModuleOpensStmt extends ModuleStmt implements NodeWithName<ModuleOpensStmt> {
-
-    private Name name;
-
-    private NodeList<Name> moduleNames;
-
-    public ModuleOpensStmt() {
-        this(null, new Name(), new NodeList<>());
-    }
-
-    @AllFieldsConstructor
-    public ModuleOpensStmt(Name name, NodeList<Name> moduleNames) {
-        this(null, name, moduleNames);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ModuleOpensStmt(TokenRange tokenRange, Name name, NodeList<Name> moduleNames) {
-        super(tokenRange);
-        setName(name);
-        setModuleNames(moduleNames);
-        customInitialization();
-    }
-
-    @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.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        for (int i = 0; i < moduleNames.size(); i++) {
-            if (moduleNames.get(i) == node) {
-                moduleNames.remove(i);
-                return true;
-            }
-        }
-        return super.remove(node);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Name getName() {
-        return name;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleOpensStmt setName(final Name name) {
-        assertNotNull(name);
-        if (name == this.name) {
-            return (ModuleOpensStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
-        if (this.name != null)
-            this.name.setParentNode(null);
-        this.name = name;
-        setAsParentNodeOf(name);
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public NodeList<Name> getModuleNames() {
-        return moduleNames;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleOpensStmt setModuleNames(final NodeList<Name> moduleNames) {
-        assertNotNull(moduleNames);
-        if (moduleNames == this.moduleNames) {
-            return (ModuleOpensStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.MODULE_NAMES, this.moduleNames, moduleNames);
-        if (this.moduleNames != null)
-            this.moduleNames.setParentNode(null);
-        this.moduleNames = moduleNames;
-        setAsParentNodeOf(moduleNames);
-        return this;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public ModuleOpensStmt clone() {
-        return (ModuleOpensStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public ModuleOpensStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.moduleOpensStmtMetaModel;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        for (int i = 0; i < moduleNames.size(); i++) {
-            if (moduleNames.get(i) == node) {
-                moduleNames.set(i, (Name) replacementNode);
-                return true;
-            }
-        }
-        if (node == name) {
-            setName((Name) replacementNode);
-            return true;
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleOpensStmt() {
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleOpensStmt asModuleOpensStmt() {
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleOpensStmt(Consumer<ModuleOpensStmt> action) {
-        action.accept(this);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleOpensStmt> toModuleOpensStmt() {
-        return Optional.of(this);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleProvidesDirective.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleProvidesDirective.java
new file mode 100644
index 0000000..d69b2d7
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleProvidesDirective.java
@@ -0,0 +1,188 @@
+package com.github.javaparser.ast.modules;
+
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.nodeTypes.NodeWithName;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+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.TokenRange;
+import java.util.function.Consumer;
+import java.util.Optional;
+import com.github.javaparser.metamodel.ModuleProvidesDirectiveMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.ast.Generated;
+
+/**
+ * A provides directive in module-info.java. <code>provides X.Y with Z1.Z2, Z3.Z4;</code>
+ */
+public class ModuleProvidesDirective extends ModuleDirective implements NodeWithName<ModuleProvidesDirective> {
+
+    private Name name;
+
+    private NodeList<Name> with;
+
+    public ModuleProvidesDirective() {
+        this(null, new Name(), new NodeList<>());
+    }
+
+    @AllFieldsConstructor
+    public ModuleProvidesDirective(Name name, NodeList<Name> with) {
+        this(null, name, with);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public ModuleProvidesDirective(TokenRange tokenRange, Name name, NodeList<Name> with) {
+        super(tokenRange);
+        setName(name);
+        setWith(with);
+        customInitialization();
+    }
+
+    @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.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < with.size(); i++) {
+            if (with.get(i) == node) {
+                with.remove(i);
+                return true;
+            }
+        }
+        return super.remove(node);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public ModuleProvidesDirective clone() {
+        return (ModuleProvidesDirective) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleProvidesStmt() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleProvidesDirective asModuleProvidesStmt() {
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleProvidesStmt(Consumer<ModuleProvidesDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleProvidesDirective> toModuleProvidesStmt() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Name getName() {
+        return name;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleProvidesDirective setName(final Name name) {
+        assertNotNull(name);
+        if (name == this.name) {
+            return (ModuleProvidesDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
+        if (this.name != null)
+            this.name.setParentNode(null);
+        this.name = name;
+        setAsParentNodeOf(name);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleProvidesDirective setWith(final NodeList<Name> with) {
+        assertNotNull(with);
+        if (with == this.with) {
+            return (ModuleProvidesDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.WITH, this.with, with);
+        if (this.with != null)
+            this.with.setParentNode(null);
+        this.with = with;
+        setAsParentNodeOf(with);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public NodeList<Name> getWith() {
+        return with;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        if (node == name) {
+            setName((Name) replacementNode);
+            return true;
+        }
+        for (int i = 0; i < with.size(); i++) {
+            if (with.get(i) == node) {
+                with.set(i, (Name) replacementNode);
+                return true;
+            }
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleProvidesDirective() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleProvidesDirective asModuleProvidesDirective() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleProvidesDirective> toModuleProvidesDirective() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleProvidesDirective(Consumer<ModuleProvidesDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ModuleProvidesDirectiveMetaModel getMetaModel() {
+        return JavaParserMetaModel.moduleProvidesDirectiveMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleProvidesStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleProvidesStmt.java
deleted file mode 100644
index 4ddbced..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleProvidesStmt.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package com.github.javaparser.ast.modules;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.nodeTypes.NodeWithType;
-import com.github.javaparser.ast.observer.ObservableProperty;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import com.github.javaparser.ast.type.Type;
-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.ModuleProvidesStmtMetaModel;
-import java.util.Arrays;
-import java.util.List;
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-import java.util.Optional;
-
-public final class ModuleProvidesStmt extends ModuleStmt implements NodeWithType<ModuleProvidesStmt, Type> {
-
-    private Type type;
-
-    private NodeList<Type> withTypes;
-
-    public ModuleProvidesStmt() {
-        this(null, new ClassOrInterfaceType(), new NodeList<>());
-    }
-
-    @AllFieldsConstructor
-    public ModuleProvidesStmt(Type type, NodeList<Type> withTypes) {
-        this(null, type, withTypes);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ModuleProvidesStmt(TokenRange tokenRange, Type type, NodeList<Type> withTypes) {
-        super(tokenRange);
-        setType(type);
-        setWithTypes(withTypes);
-        customInitialization();
-    }
-
-    @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.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        for (int i = 0; i < withTypes.size(); i++) {
-            if (withTypes.get(i) == node) {
-                withTypes.remove(i);
-                return true;
-            }
-        }
-        return super.remove(node);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Type getType() {
-        return type;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleProvidesStmt setType(final Type type) {
-        assertNotNull(type);
-        if (type == this.type) {
-            return (ModuleProvidesStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.TYPE, this.type, type);
-        if (this.type != null)
-            this.type.setParentNode(null);
-        this.type = type;
-        setAsParentNodeOf(type);
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public NodeList<Type> getWithTypes() {
-        return withTypes;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleProvidesStmt setWithTypes(final NodeList<Type> withTypes) {
-        assertNotNull(withTypes);
-        if (withTypes == this.withTypes) {
-            return (ModuleProvidesStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.WITH_TYPES, this.withTypes, withTypes);
-        if (this.withTypes != null)
-            this.withTypes.setParentNode(null);
-        this.withTypes = withTypes;
-        setAsParentNodeOf(withTypes);
-        return this;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public ModuleProvidesStmt clone() {
-        return (ModuleProvidesStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public ModuleProvidesStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.moduleProvidesStmtMetaModel;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        if (node == type) {
-            setType((Type) replacementNode);
-            return true;
-        }
-        for (int i = 0; i < withTypes.size(); i++) {
-            if (withTypes.get(i) == node) {
-                withTypes.set(i, (Type) replacementNode);
-                return true;
-            }
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleProvidesStmt() {
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleProvidesStmt asModuleProvidesStmt() {
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleProvidesStmt(Consumer<ModuleProvidesStmt> action) {
-        action.accept(this);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleProvidesStmt> toModuleProvidesStmt() {
-        return Optional.of(this);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleRequiresDirective.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleRequiresDirective.java
new file mode 100644
index 0000000..5d97293
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleRequiresDirective.java
@@ -0,0 +1,199 @@
+package com.github.javaparser.ast.modules;
+
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.nodeTypes.NodeWithName;
+import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithStaticModifier;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.ast.visitor.GenericVisitor;
+import com.github.javaparser.ast.visitor.VoidVisitor;
+import static com.github.javaparser.ast.Modifier.Keyword.TRANSITIVE;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.TokenRange;
+import java.util.function.Consumer;
+import java.util.Optional;
+import com.github.javaparser.metamodel.ModuleRequiresDirectiveMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.ast.Generated;
+
+/**
+ * A require directive in module-info.java. <code>require a.b.C;</code>
+ */
+public class ModuleRequiresDirective extends ModuleDirective implements NodeWithStaticModifier<ModuleRequiresDirective>, NodeWithName<ModuleRequiresDirective> {
+
+    private NodeList<Modifier> modifiers;
+
+    private Name name;
+
+    public ModuleRequiresDirective() {
+        this(null, new NodeList<>(), new Name());
+    }
+
+    @AllFieldsConstructor
+    public ModuleRequiresDirective(NodeList<Modifier> modifiers, Name name) {
+        this(null, modifiers, name);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public ModuleRequiresDirective(TokenRange tokenRange, NodeList<Modifier> modifiers, Name name) {
+        super(tokenRange);
+        setModifiers(modifiers);
+        setName(name);
+        customInitialization();
+    }
+
+    @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);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public NodeList<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleRequiresDirective setModifiers(final NodeList<Modifier> modifiers) {
+        assertNotNull(modifiers);
+        if (modifiers == this.modifiers) {
+            return (ModuleRequiresDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
+        if (this.modifiers != null)
+            this.modifiers.setParentNode(null);
+        this.modifiers = modifiers;
+        setAsParentNodeOf(modifiers);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Name getName() {
+        return name;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleRequiresDirective setName(final Name name) {
+        assertNotNull(name);
+        if (name == this.name) {
+            return (ModuleRequiresDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
+        if (this.name != null)
+            this.name.setParentNode(null);
+        this.name = name;
+        setAsParentNodeOf(name);
+        return this;
+    }
+
+    public boolean isTransitive() {
+        return hasModifier(TRANSITIVE);
+    }
+
+    public ModuleRequiresDirective setTransitive(boolean set) {
+        return setModifier(TRANSITIVE, set);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.remove(i);
+                return true;
+            }
+        }
+        return super.remove(node);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public ModuleRequiresDirective clone() {
+        return (ModuleRequiresDirective) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < modifiers.size(); i++) {
+            if (modifiers.get(i) == node) {
+                modifiers.set(i, (Modifier) replacementNode);
+                return true;
+            }
+        }
+        if (node == name) {
+            setName((Name) replacementNode);
+            return true;
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleRequiresStmt() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleRequiresDirective asModuleRequiresStmt() {
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleRequiresStmt(Consumer<ModuleRequiresDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleRequiresDirective> toModuleRequiresStmt() {
+        return Optional.of(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleRequiresDirective() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleRequiresDirective asModuleRequiresDirective() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleRequiresDirective> toModuleRequiresDirective() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleRequiresDirective(Consumer<ModuleRequiresDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ModuleRequiresDirectiveMetaModel getMetaModel() {
+        return JavaParserMetaModel.moduleRequiresDirectiveMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleRequiresStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleRequiresStmt.java
deleted file mode 100644
index cede81c..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleRequiresStmt.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.github.javaparser.ast.modules;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.nodeTypes.NodeWithName;
-import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithStaticModifier;
-import com.github.javaparser.ast.observer.ObservableProperty;
-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.ModuleRequiresStmtMetaModel;
-import java.util.EnumSet;
-import static com.github.javaparser.ast.Modifier.TRANSITIVE;
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-import java.util.Optional;
-
-/**
- * A require statement in module-info.java. <code>require a.b.C;</code>
- */
-public final class ModuleRequiresStmt extends ModuleStmt implements NodeWithStaticModifier<ModuleRequiresStmt>, NodeWithName<ModuleRequiresStmt> {
-
-    private EnumSet<Modifier> modifiers;
-
-    private Name name;
-
-    public ModuleRequiresStmt() {
-        this(null, EnumSet.noneOf(Modifier.class), new Name());
-    }
-
-    @AllFieldsConstructor
-    public ModuleRequiresStmt(EnumSet<Modifier> modifiers, Name name) {
-        this(null, modifiers, name);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ModuleRequiresStmt(TokenRange tokenRange, EnumSet<Modifier> modifiers, Name name) {
-        super(tokenRange);
-        setModifiers(modifiers);
-        setName(name);
-        customInitialization();
-    }
-
-    @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);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public EnumSet<Modifier> getModifiers() {
-        return modifiers;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleRequiresStmt setModifiers(final EnumSet<Modifier> modifiers) {
-        assertNotNull(modifiers);
-        if (modifiers == this.modifiers) {
-            return (ModuleRequiresStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
-        this.modifiers = modifiers;
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Name getName() {
-        return name;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleRequiresStmt setName(final Name name) {
-        assertNotNull(name);
-        if (name == this.name) {
-            return (ModuleRequiresStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
-        if (this.name != null)
-            this.name.setParentNode(null);
-        this.name = name;
-        setAsParentNodeOf(name);
-        return this;
-    }
-
-    public boolean isTransitive() {
-        return getModifiers().contains(TRANSITIVE);
-    }
-
-    public ModuleRequiresStmt setTransitive(boolean set) {
-        return setModifier(TRANSITIVE, set);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        return super.remove(node);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public ModuleRequiresStmt clone() {
-        return (ModuleRequiresStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public ModuleRequiresStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.moduleRequiresStmtMetaModel;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        if (node == name) {
-            setName((Name) replacementNode);
-            return true;
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleRequiresStmt() {
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleRequiresStmt asModuleRequiresStmt() {
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleRequiresStmt(Consumer<ModuleRequiresStmt> action) {
-        action.accept(this);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleRequiresStmt> toModuleRequiresStmt() {
-        return Optional.of(this);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleStmt.java
deleted file mode 100644
index 176c791..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleStmt.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.github.javaparser.ast.modules;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.visitor.CloneVisitor;
-import com.github.javaparser.metamodel.JavaParserMetaModel;
-import com.github.javaparser.metamodel.ModuleStmtMetaModel;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-import static com.github.javaparser.utils.CodeGenerationUtils.f;
-import java.util.Optional;
-
-public abstract class ModuleStmt extends Node {
-
-    @AllFieldsConstructor
-    public ModuleStmt() {
-        this(null);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ModuleStmt(TokenRange tokenRange) {
-        super(tokenRange);
-        customInitialization();
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        return super.remove(node);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public ModuleStmt clone() {
-        return (ModuleStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public ModuleStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.moduleStmtMetaModel;
-    }
-
-    @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);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleExportsStmt() {
-        return false;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleExportsStmt asModuleExportsStmt() {
-        throw new IllegalStateException(f("%s is not an ModuleExportsStmt", this));
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleOpensStmt() {
-        return false;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleOpensStmt asModuleOpensStmt() {
-        throw new IllegalStateException(f("%s is not an ModuleOpensStmt", this));
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleProvidesStmt() {
-        return false;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleProvidesStmt asModuleProvidesStmt() {
-        throw new IllegalStateException(f("%s is not an ModuleProvidesStmt", this));
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleRequiresStmt() {
-        return false;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleRequiresStmt asModuleRequiresStmt() {
-        throw new IllegalStateException(f("%s is not an ModuleRequiresStmt", this));
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleUsesStmt() {
-        return false;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleUsesStmt asModuleUsesStmt() {
-        throw new IllegalStateException(f("%s is not an ModuleUsesStmt", this));
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleExportsStmt(Consumer<ModuleExportsStmt> action) {
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleOpensStmt(Consumer<ModuleOpensStmt> action) {
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleProvidesStmt(Consumer<ModuleProvidesStmt> action) {
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleRequiresStmt(Consumer<ModuleRequiresStmt> action) {
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleUsesStmt(Consumer<ModuleUsesStmt> action) {
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleExportsStmt> toModuleExportsStmt() {
-        return Optional.empty();
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleOpensStmt> toModuleOpensStmt() {
-        return Optional.empty();
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleProvidesStmt> toModuleProvidesStmt() {
-        return Optional.empty();
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleRequiresStmt> toModuleRequiresStmt() {
-        return Optional.empty();
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleUsesStmt> toModuleUsesStmt() {
-        return Optional.empty();
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleUsesDirective.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleUsesDirective.java
new file mode 100644
index 0000000..8779098
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleUsesDirective.java
@@ -0,0 +1,167 @@
+package com.github.javaparser.ast.modules;
+
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.nodeTypes.NodeWithName;
+import com.github.javaparser.ast.observer.ObservableProperty;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.ast.visitor.GenericVisitor;
+import com.github.javaparser.ast.visitor.VoidVisitor;
+import java.util.Optional;
+import java.util.function.Consumer;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.metamodel.ModuleUsesDirectiveMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import com.github.javaparser.ast.Generated;
+
+/**
+ * A uses directive in module-info.java. <code>uses V.W;</code>
+ */
+public class ModuleUsesDirective extends ModuleDirective implements NodeWithName<ModuleUsesDirective> {
+
+    private Name name;
+
+    public ModuleUsesDirective() {
+        this(null, new Name());
+    }
+
+    @AllFieldsConstructor
+    public ModuleUsesDirective(Name name) {
+        this(null, name);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public ModuleUsesDirective(TokenRange tokenRange, Name name) {
+        super(tokenRange);
+        setName(name);
+        customInitialization();
+    }
+
+    @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.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        return super.remove(node);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleUsesDirective setType(final Name name) {
+        assertNotNull(name);
+        if (name == this.name) {
+            return (ModuleUsesDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.TYPE, this.name, name);
+        if (this.name != null)
+            this.name.setParentNode(null);
+        this.name = name;
+        setAsParentNodeOf(name);
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public ModuleUsesDirective clone() {
+        return (ModuleUsesDirective) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleUsesStmt() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleUsesDirective asModuleUsesStmt() {
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleUsesStmt(Consumer<ModuleUsesDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleUsesDirective> toModuleUsesStmt() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Name getName() {
+        return name;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ModuleUsesDirective setName(final Name name) {
+        assertNotNull(name);
+        if (name == this.name) {
+            return (ModuleUsesDirective) this;
+        }
+        notifyPropertyChange(ObservableProperty.NAME, this.name, name);
+        if (this.name != null)
+            this.name.setParentNode(null);
+        this.name = name;
+        setAsParentNodeOf(name);
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        if (node == name) {
+            setName((Name) replacementNode);
+            return true;
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isModuleUsesDirective() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ModuleUsesDirective asModuleUsesDirective() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ModuleUsesDirective> toModuleUsesDirective() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifModuleUsesDirective(Consumer<ModuleUsesDirective> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ModuleUsesDirectiveMetaModel getMetaModel() {
+        return JavaParserMetaModel.moduleUsesDirectiveMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleUsesStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleUsesStmt.java
deleted file mode 100644
index 2bf9856..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/modules/ModuleUsesStmt.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.github.javaparser.ast.modules;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.nodeTypes.NodeWithType;
-import com.github.javaparser.ast.observer.ObservableProperty;
-import com.github.javaparser.ast.type.Type;
-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.ModuleUsesStmtMetaModel;
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-import java.util.Optional;
-
-public final class ModuleUsesStmt extends ModuleStmt implements NodeWithType<ModuleUsesStmt, Type> {
-
-    private Type type;
-
-    public ModuleUsesStmt() {
-        this(null);
-    }
-
-    @AllFieldsConstructor
-    public ModuleUsesStmt(Type type) {
-        this(null, type);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ModuleUsesStmt(TokenRange tokenRange, Type type) {
-        super(tokenRange);
-        setType(type);
-        customInitialization();
-    }
-
-    @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.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        return super.remove(node);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Type getType() {
-        return type;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ModuleUsesStmt setType(final Type type) {
-        assertNotNull(type);
-        if (type == this.type) {
-            return (ModuleUsesStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.TYPE, this.type, type);
-        if (this.type != null)
-            this.type.setParentNode(null);
-        this.type = type;
-        setAsParentNodeOf(type);
-        return this;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public ModuleUsesStmt clone() {
-        return (ModuleUsesStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public ModuleUsesStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.moduleUsesStmtMetaModel;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        if (node == type) {
-            setType((Type) replacementNode);
-            return true;
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isModuleUsesStmt() {
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ModuleUsesStmt asModuleUsesStmt() {
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifModuleUsesStmt(Consumer<ModuleUsesStmt> action) {
-        action.accept(this);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ModuleUsesStmt> toModuleUsesStmt() {
-        return Optional.of(this);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithAnnotations.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithAnnotations.java
index 72060c6..c7b1bd2 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithAnnotations.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithAnnotations.java
@@ -28,8 +28,8 @@
 import java.lang.annotation.Annotation;
 import java.util.Optional;
 
-import static com.github.javaparser.JavaParser.parseExpression;
-import static com.github.javaparser.JavaParser.parseName;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static com.github.javaparser.StaticJavaParser.parseName;
 
 /**
  * A node that can be annotated.
@@ -70,7 +70,7 @@
     default N addAnnotation(String name) {
         NormalAnnotationExpr annotation = new NormalAnnotationExpr(
                 parseName(name), new NodeList<>());
-        getAnnotations().add(annotation);
+        addAnnotation(annotation);
         return (N) this;
     }
 
@@ -84,7 +84,7 @@
     default NormalAnnotationExpr addAndGetAnnotation(String name) {
         NormalAnnotationExpr annotation = new NormalAnnotationExpr(
                 parseName(name), new NodeList<>());
-        getAnnotations().add(annotation);
+        addAnnotation(annotation);
         return annotation;
     }
 
@@ -120,7 +120,7 @@
     default N addMarkerAnnotation(String name) {
         MarkerAnnotationExpr markerAnnotationExpr = new MarkerAnnotationExpr(
                 parseName(name));
-        getAnnotations().add(markerAnnotationExpr);
+        addAnnotation(markerAnnotationExpr);
         return (N) this;
     }
 
@@ -146,8 +146,19 @@
     default N addSingleMemberAnnotation(String name, Expression expression) {
         SingleMemberAnnotationExpr singleMemberAnnotationExpr = new SingleMemberAnnotationExpr(
                 parseName(name), expression);
-        getAnnotations().add(singleMemberAnnotationExpr);
-        return (N) this;
+        return addAnnotation(singleMemberAnnotationExpr);
+    }
+
+    /**
+     * Annotates this with a single member annotation
+     *
+     * @param clazz the class of the annotation
+     * @param expression the part between ()
+     * @return this
+     */
+    default N addSingleMemberAnnotation(Class<? extends Annotation> clazz, Expression expression) {
+        tryAddImportToParentCompilationUnit(clazz);
+        return addSingleMemberAnnotation(clazz.getSimpleName(), expression);
     }
 
     /**
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithArguments.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithArguments.java
index 702707c..c073534 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithArguments.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithArguments.java
@@ -25,7 +25,7 @@
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.expr.Expression;
 
-import static com.github.javaparser.JavaParser.parseExpression;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
 
 /**
  * A node with arguments.
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithBody.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithBody.java
index 2388824..0577ae2 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithBody.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithBody.java
@@ -1,38 +1,49 @@
-/*

- * 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.nodeTypes;

-

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.stmt.BlockStmt;

-import com.github.javaparser.ast.stmt.Statement;

-

-public interface NodeWithBody<N extends Node> {

-    Statement getBody();

-

-    N setBody(final Statement body);

-

-    default BlockStmt createBlockStatementAsBody() {

-        BlockStmt b = new BlockStmt();

-        setBody(b);

-        return b;

-    }

-}

+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.EmptyStmt;
+import com.github.javaparser.ast.stmt.Statement;
+
+public interface NodeWithBody<N extends Node> {
+    Statement getBody();
+
+    N setBody(final Statement body);
+
+    default BlockStmt createBlockStatementAsBody() {
+        BlockStmt b = new BlockStmt();
+        setBody(b);
+        return b;
+    }
+
+    /**
+     * @return true if the body is an {@link EmptyStmt} or an empty {@link BlockStmt}
+     */
+    default boolean hasEmptyBody() {
+        Statement body = getBody();
+        return body.toBlockStmt().map(bs -> bs.isEmpty())
+                .orElse(body.isEmptyStmt());
+    }
+
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithConstructors.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithConstructors.java
index b2f2507..605ff51 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithConstructors.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithConstructors.java
@@ -4,13 +4,11 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.ConstructorDeclaration;
 
-import java.util.Arrays;
-import java.util.EnumSet;
 import java.util.List;
 import java.util.Optional;
 
+import static com.github.javaparser.ast.Modifier.createModifierList;
 import static java.util.Collections.unmodifiableList;
-import static java.util.stream.Collectors.toCollection;
 import static java.util.stream.Collectors.toList;
 
 public interface NodeWithConstructors<N extends Node> extends NodeWithSimpleName<N>, NodeWithMembers<N> {
@@ -26,12 +24,12 @@
     /**
      * Adds a constructor to this
      *
-     * @param modifiers the modifiers like {@link Modifier#PUBLIC}
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
      * @return the created constructor
      */
-    default ConstructorDeclaration addConstructor(Modifier... modifiers) {
+    default ConstructorDeclaration addConstructor(Modifier.Keyword... modifiers) {
         ConstructorDeclaration constructorDeclaration = new ConstructorDeclaration();
-        constructorDeclaration.setModifiers(Arrays.stream(modifiers).collect(toCollection(() -> EnumSet.noneOf(Modifier.class))));
+        constructorDeclaration.setModifiers(createModifierList(modifiers));
         constructorDeclaration.setName(getName());
         getMembers().add(constructorDeclaration);
         return constructorDeclaration;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithDeclaration.java
index d490ed1..8f67d49 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithDeclaration.java
@@ -35,7 +35,9 @@
      *
      * @return String representation of declaration
      */
-    String getDeclarationAsString();
+    default String getDeclarationAsString() {
+        return getDeclarationAsString(true, true, true);
+    }
 
     /**
      * As {@link NodeWithDeclaration#getDeclarationAsString(boolean, boolean, boolean)} including
@@ -45,7 +47,9 @@
      * @param includingThrows flag to include the throws clause (if present) in the string produced
      * @return String representation of declaration based on parameter flags
      */
-    String getDeclarationAsString(boolean includingModifiers, boolean includingThrows);
+    default String getDeclarationAsString(boolean includingModifiers, boolean includingThrows) {
+        return getDeclarationAsString(includingModifiers, includingThrows, true);
+    }
 
     /**
      * A simple representation of the element declaration.
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExpression.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExpression.java
index 3a1dd71..f5f58e9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExpression.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExpression.java
@@ -24,7 +24,7 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.expr.Expression;
 
-import static com.github.javaparser.JavaParser.parseExpression;
+import static com.github.javaparser.StaticJavaParser.parseExpression;
 
 /**
  * A node that has an expression in it.
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExtends.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExtends.java
index af4adf8..1627f1c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExtends.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithExtends.java
@@ -1,92 +1,92 @@
-/*

- * 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.nodeTypes;

-

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.NodeList;

-import com.github.javaparser.ast.type.ClassOrInterfaceType;

-

-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;

-

-/**

- * A node that extends other types.

- */

-public interface NodeWithExtends<N extends Node> {

-    NodeList<ClassOrInterfaceType> getExtendedTypes();

-

-    void tryAddImportToParentCompilationUnit(Class<?> clazz);

-

-    default ClassOrInterfaceType getExtendedTypes(int i) {

-        return getExtendedTypes().get(i);

-    }

-

-    N setExtendedTypes(NodeList<ClassOrInterfaceType> extendsList);

-

-    @SuppressWarnings("unchecked")

-    default N setExtendedType(int i, ClassOrInterfaceType extend) {

-        getExtendedTypes().set(i, extend);

-        return (N) this;

-    }

-

-    @SuppressWarnings("unchecked")

-    default N addExtendedType(ClassOrInterfaceType extend) {

-        getExtendedTypes().add(extend);

-        return (N) this;

-    }

-

-    /**

-     * @deprecated use addExtendedType

-     */

-    default N addExtends(Class<?> clazz) {

-        return addExtendedType(clazz);

-    }

-

-    /**

-     * @deprecated use addExtendedType

-     */

-    default N addExtends(String name) {

-        return addExtendedType(name);

-    }

-

-    /**

-     * Add an "extends" to this and automatically add the import

-     *

-     * @param clazz the class to extand from

-     * @return this

-     */

-    default N addExtendedType(Class<?> clazz) {

-        tryAddImportToParentCompilationUnit(clazz);

-        return addExtendedType(clazz.getSimpleName());

-    }

-

-    /**

-     * Add an "extends" to this

-     *

-     * @param name the name of the type to extends from

-     * @return this

-     */

-    @SuppressWarnings("unchecked")

-    default N addExtendedType(String name) {

-        getExtendedTypes().add(parseClassOrInterfaceType(name));

-        return (N) this;

-    }

-}

+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+
+import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
+
+/**
+ * A node that extends other types.
+ */
+public interface NodeWithExtends<N extends Node> {
+    NodeList<ClassOrInterfaceType> getExtendedTypes();
+
+    void tryAddImportToParentCompilationUnit(Class<?> clazz);
+
+    default ClassOrInterfaceType getExtendedTypes(int i) {
+        return getExtendedTypes().get(i);
+    }
+
+    N setExtendedTypes(NodeList<ClassOrInterfaceType> extendsList);
+
+    @SuppressWarnings("unchecked")
+    default N setExtendedType(int i, ClassOrInterfaceType extend) {
+        getExtendedTypes().set(i, extend);
+        return (N) this;
+    }
+
+    @SuppressWarnings("unchecked")
+    default N addExtendedType(ClassOrInterfaceType extend) {
+        getExtendedTypes().add(extend);
+        return (N) this;
+    }
+
+    /**
+     * @deprecated use addExtendedType
+     */
+    default N addExtends(Class<?> clazz) {
+        return addExtendedType(clazz);
+    }
+
+    /**
+     * @deprecated use addExtendedType
+     */
+    default N addExtends(String name) {
+        return addExtendedType(name);
+    }
+
+    /**
+     * Add an "extends" to this and automatically add the import
+     *
+     * @param clazz the class to extand from
+     * @return this
+     */
+    default N addExtendedType(Class<?> clazz) {
+        tryAddImportToParentCompilationUnit(clazz);
+        return addExtendedType(clazz.getSimpleName());
+    }
+
+    /**
+     * Add an "extends" to this
+     *
+     * @param name the name of the type to extends from
+     * @return this
+     */
+    @SuppressWarnings("unchecked")
+    default N addExtendedType(String name) {
+        getExtendedTypes().add(parseClassOrInterfaceType(name));
+        return (N) this;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithImplements.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithImplements.java
index 84cee4d..9206d3b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithImplements.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithImplements.java
@@ -1,88 +1,88 @@
-/*

- * 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.nodeTypes;

-

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.NodeList;

-import com.github.javaparser.ast.type.ClassOrInterfaceType;

-

-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;

-

-/**

- * A node that implements other types.

- */

-public interface NodeWithImplements<N extends Node> {

-    NodeList<ClassOrInterfaceType> getImplementedTypes();

-

-    default ClassOrInterfaceType getImplementedTypes(int i) {

-        return getImplementedTypes().get(i);

-    }

-

-    N setImplementedTypes(NodeList<ClassOrInterfaceType> implementsList);

-    

-    void tryAddImportToParentCompilationUnit(Class<?> clazz);

-    

-    @SuppressWarnings("unchecked")

-    default N setImplementedType(int i, ClassOrInterfaceType implement) {

-        getImplementedTypes().set(i, implement);

-        return (N) this;

-    }

-

-    @SuppressWarnings("unchecked")

-    default N addImplementedType(ClassOrInterfaceType implement) {

-        getImplementedTypes().add(implement);

-        return (N) this;

-    }

-

-    /** @deprecated use addImplementedType instead */

-    default N addImplements(String name) {

-        return addImplementedType(name);

-    }

-

-    /** @deprecated use addImplementedType instead */

-    default N addImplements(Class<?> clazz) {

-        return addImplementedType(clazz);

-    }

-

-    /**

-     * Add an implements to this

-     *

-     * @param name the name of the type to extends from

-     * @return this

-     */

-    @SuppressWarnings("unchecked")

-    default N addImplementedType(String name) {

-        getImplementedTypes().add(parseClassOrInterfaceType(name));

-        return (N) this;

-    }

-

-    /**

-     * Add an implements to this and automatically add the import

-     *

-     * @param clazz the type to implements from

-     * @return this

-     */

-    default N addImplementedType(Class<?> clazz) {

-        tryAddImportToParentCompilationUnit(clazz);

-        return addImplementedType(clazz.getSimpleName());

-    }

-}

+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+
+import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
+
+/**
+ * A node that implements other types.
+ */
+public interface NodeWithImplements<N extends Node> {
+    NodeList<ClassOrInterfaceType> getImplementedTypes();
+
+    default ClassOrInterfaceType getImplementedTypes(int i) {
+        return getImplementedTypes().get(i);
+    }
+
+    N setImplementedTypes(NodeList<ClassOrInterfaceType> implementsList);
+    
+    void tryAddImportToParentCompilationUnit(Class<?> clazz);
+    
+    @SuppressWarnings("unchecked")
+    default N setImplementedType(int i, ClassOrInterfaceType implement) {
+        getImplementedTypes().set(i, implement);
+        return (N) this;
+    }
+
+    @SuppressWarnings("unchecked")
+    default N addImplementedType(ClassOrInterfaceType implement) {
+        getImplementedTypes().add(implement);
+        return (N) this;
+    }
+
+    /** @deprecated use addImplementedType instead */
+    default N addImplements(String name) {
+        return addImplementedType(name);
+    }
+
+    /** @deprecated use addImplementedType instead */
+    default N addImplements(Class<?> clazz) {
+        return addImplementedType(clazz);
+    }
+
+    /**
+     * Add an implements to this
+     *
+     * @param name the name of the type to extends from
+     * @return this
+     */
+    @SuppressWarnings("unchecked")
+    default N addImplementedType(String name) {
+        getImplementedTypes().add(parseClassOrInterfaceType(name));
+        return (N) this;
+    }
+
+    /**
+     * Add an implements to this and automatically add the import
+     *
+     * @param clazz the type to implements from
+     * @return this
+     */
+    default N addImplementedType(Class<?> clazz) {
+        tryAddImportToParentCompilationUnit(clazz);
+        return addImplementedType(clazz.getSimpleName());
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadoc.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadoc.java
index 592947e..83605a9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadoc.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadoc.java
@@ -64,7 +64,7 @@
      */
     @SuppressWarnings("unchecked")
     default N setJavadocComment(String comment) {
-        return setJavadocComment(new JavadocComment(" " + comment));
+        return setJavadocComment(new JavadocComment(comment));
     }
 
     default N setJavadocComment(JavadocComment comment) {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java
index 6d5f0c3..5f74faa 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithMembers.java
@@ -1,328 +1,393 @@
-/*

- * 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.nodeTypes;

-

-import com.github.javaparser.ast.Modifier;

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.NodeList;

-import com.github.javaparser.ast.body.*;

-import com.github.javaparser.ast.expr.Expression;

-import com.github.javaparser.ast.stmt.BlockStmt;

-import com.github.javaparser.ast.type.Type;

-import com.github.javaparser.ast.type.VoidType;

-

-import java.util.Arrays;

-import java.util.EnumSet;

-import java.util.List;

-import java.util.Optional;

-

-import static com.github.javaparser.JavaParser.parseType;

-import static java.util.Collections.unmodifiableList;

-import static java.util.stream.Collectors.toCollection;

-import static java.util.stream.Collectors.toList;

-

-/**

- * A node having members.

- * <p>

- * The main reason for this interface is to permit users to manipulate homogeneously all nodes with a getMembers

- * method.

- */

-public interface NodeWithMembers<N extends Node> {

-    /**

-     * @return all members inside the braces of this node,

-     * like fields, methods, nested types, etc.

-     */

-    NodeList<BodyDeclaration<?>> getMembers();

-

-    void tryAddImportToParentCompilationUnit(Class<?> clazz);

-

-    default BodyDeclaration<?> getMember(int i) {

-        return getMembers().get(i);

-    }

-

-    @SuppressWarnings("unchecked")

-    default N setMember(int i, BodyDeclaration<?> member) {

-        getMembers().set(i, member);

-        return (N) this;

-    }

-

-    @SuppressWarnings("unchecked")

-    default N addMember(BodyDeclaration<?> member) {

-        getMembers().add(member);

-        return (N) this;

-    }

-

-    N setMembers(NodeList<BodyDeclaration<?>> members);

-

-    /**

-     * Add a field to this and automatically add the import of the type if needed

-     *

-     * @param typeClass the type of the field

-     * @param name the name of the field

-     * @param modifiers the modifiers like {@link Modifier#PUBLIC}

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addField(Class<?> typeClass, String name, Modifier... modifiers) {

-        tryAddImportToParentCompilationUnit(typeClass);

-        return addField(typeClass.getSimpleName(), name, modifiers);

-    }

-

-    /**

-     * Add a field to this.

-     *

-     * @param type the type of the field

-     * @param name the name of the field

-     * @param modifiers the modifiers like {@link Modifier#PUBLIC}

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addField(String type, String name, Modifier... modifiers) {

-        return addField(parseType(type), name, modifiers);

-    }

-

-    /**

-     * Add a field to this.

-     *

-     * @param type the type of the field

-     * @param name the name of the field

-     * @param modifiers the modifiers like {@link Modifier#PUBLIC}

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addField(Type type, String name, Modifier... modifiers) {

-        FieldDeclaration fieldDeclaration = new FieldDeclaration();

-        VariableDeclarator variable = new VariableDeclarator(type, name);

-        fieldDeclaration.getVariables().add(variable);

-        fieldDeclaration.setModifiers(Arrays.stream(modifiers)

-                .collect(toCollection(() -> EnumSet.noneOf(Modifier.class))));

-        getMembers().add(fieldDeclaration);

-        return fieldDeclaration;

-    }

-

-    /**

-     * Add a field to this.

-     *

-     * @param type the type of the field

-     * @param name the name of the field

-     * @param initializer the initializer of the field

-     * @param modifiers the modifiers like {@link Modifier#PUBLIC}

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addFieldWithInitializer(Type type, String name, Expression initializer, Modifier... modifiers) {

-        FieldDeclaration declaration = addField(type, name, modifiers);

-        declaration.getVariables().iterator().next().setInitializer(initializer);

-        return declaration;

-    }

-

-    /**

-     * Add a private field to this.

-     *

-     * @param typeClass the type of the field

-     * @param name the name of the field

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addPrivateField(Class<?> typeClass, String name) {

-        return addField(typeClass, name, Modifier.PRIVATE);

-    }

-

-    /**

-     * Add a private field to this and automatically add the import of the type if

-     * needed.

-     *

-     * @param type the type of the field

-     * @param name the name of the field

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addPrivateField(String type, String name) {

-        return addField(type, name, Modifier.PRIVATE);

-    }

-

-    /**

-     * Add a public field to this.

-     *

-     * @param typeClass the type of the field

-     * @param name the name of the field

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addPublicField(Class<?> typeClass, String name) {

-        return addField(typeClass, name, Modifier.PUBLIC);

-    }

-

-    /**

-     * Add a public field to this and automatically add the import of the type if

-     * needed.

-     *

-     * @param type the type of the field

-     * @param name the name of the field

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addPublicField(String type, String name) {

-        return addField(type, name, Modifier.PUBLIC);

-    }

-

-    /**

-     * Add a protected field to this.

-     *

-     * @param typeClass the type of the field

-     * @param name the name of the field

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addProtectedField(Class<?> typeClass, String name) {

-        return addField(typeClass, name, Modifier.PROTECTED);

-    }

-

-    /**

-     * Add a protected field to this and automatically add the import of the type

-     * if needed.

-     *

-     * @param type the type of the field

-     * @param name the name of the field

-     * @return the {@link FieldDeclaration} created

-     */

-    default FieldDeclaration addProtectedField(String type, String name) {

-        return addField(type, name, Modifier.PROTECTED);

-    }

-

-    /**

-     * Adds a methods with void return by default to this.

-     *

-     * @param methodName the method name

-     * @param modifiers the modifiers like {@link Modifier#PUBLIC}

-     * @return the {@link MethodDeclaration} created

-     */

-    default MethodDeclaration addMethod(String methodName, Modifier... modifiers) {

-        MethodDeclaration methodDeclaration = new MethodDeclaration();

-        methodDeclaration.setName(methodName);

-        methodDeclaration.setType(new VoidType());

-        methodDeclaration.setModifiers(Arrays.stream(modifiers)

-                .collect(toCollection(() -> EnumSet.noneOf(Modifier.class))));

-        getMembers().add(methodDeclaration);

-        return methodDeclaration;

-    }

-

-    /**

-     * Add an initializer block ({@link InitializerDeclaration}) to this.

-     */

-    default BlockStmt addInitializer() {

-        BlockStmt block = new BlockStmt();

-        InitializerDeclaration initializerDeclaration = new InitializerDeclaration(false, block);

-        getMembers().add(initializerDeclaration);

-        return block;

-    }

-

-    /**

-     * Add a static initializer block ({@link InitializerDeclaration}) to this.

-     */

-    default BlockStmt addStaticInitializer() {

-        BlockStmt block = new BlockStmt();

-        InitializerDeclaration initializerDeclaration = new InitializerDeclaration(true, block);

-        getMembers().add(initializerDeclaration);

-        return block;

-    }

-

-    /**

-     * Try to find a {@link MethodDeclaration} by its name

-     *

-     * @param name the name of the method

-     * @return the methods found (multiple in case of overloading)

-     */

-    default List<MethodDeclaration> getMethodsByName(String name) {

-        return unmodifiableList(getMethods().stream()

-                .filter(m -> m.getNameAsString().equals(name))

-                .collect(toList()));

-    }

-

-    /**

-     * Find all methods in the members of this node.

-     *

-     * @return the methods found. This list is immutable.

-     */

-    default List<MethodDeclaration> getMethods() {

-        return unmodifiableList(getMembers().stream()

-                .filter(m -> m instanceof MethodDeclaration)

-                .map(m -> (MethodDeclaration) m)

-                .collect(toList()));

-    }

-

-    /**

-     * Try to find a {@link MethodDeclaration} by its parameters types

-     *

-     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void

-     * foo(Map&lt;Integer,String&gt; myMap,int number)

-     * @return the methods found (multiple in case of overloading)

-     */

-    default List<MethodDeclaration> getMethodsByParameterTypes(String... paramTypes) {

-        return unmodifiableList(getMethods().stream()

-                .filter(m -> m.hasParametersOfType(paramTypes))

-                .collect(toList()));

-    }

-

-    /**

-     * Try to find {@link MethodDeclaration}s by their name and parameters types

-     *

-     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void

-     * foo(Map&lt;Integer,String&gt; myMap,int number)

-     * @return the methods found (multiple in case of overloading)

-     */

-    default List<MethodDeclaration> getMethodsBySignature(String name, String... paramTypes) {

-        return unmodifiableList(getMethodsByName(name).stream()

-                .filter(m -> m.hasParametersOfType(paramTypes))

-                .collect(toList()));

-    }

-

-    /**

-     * Try to find a {@link MethodDeclaration} by its parameters types

-     *

-     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void

-     * foo(Map&lt;Integer,String&gt; myMap,int number)

-     * @return the methods found (multiple in case of overloading)

-     */

-    default List<MethodDeclaration> getMethodsByParameterTypes(Class<?>... paramTypes) {

-        return unmodifiableList(getMethods().stream()

-                .filter(m -> m.hasParametersOfType(paramTypes))

-                .collect(toList()));

-    }

-

-    /**

-     * Try to find a {@link FieldDeclaration} by its name

-     *

-     * @param name the name of the field

-     * @return null if not found, the FieldDeclaration otherwise

-     */

-    default Optional<FieldDeclaration> getFieldByName(String name) {

-        return getMembers().stream()

-                .filter(m -> m instanceof FieldDeclaration)

-                .map(f -> (FieldDeclaration) f)

-                .filter(f -> f.getVariables().stream()

-                        .anyMatch(var -> var.getNameAsString().equals(name)))

-                .findFirst();

-    }

-

-    /**

-     * Find all fields in the members of this node.

-     *

-     * @return the fields found. This list is immutable.

-     */

-    default List<FieldDeclaration> getFields() {

-        return unmodifiableList(getMembers().stream()

-                .filter(m -> m instanceof FieldDeclaration)

-                .map(m -> (FieldDeclaration) m)

-                .collect(toList()));

-    }

-}

+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.type.Type;
+import com.github.javaparser.ast.type.VoidType;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.github.javaparser.StaticJavaParser.parseType;
+import static com.github.javaparser.ast.Modifier.Keyword;
+import static com.github.javaparser.ast.Modifier.Keyword.*;
+import static com.github.javaparser.ast.Modifier.createModifierList;
+import static java.util.Collections.unmodifiableList;
+import static java.util.stream.Collectors.toList;
+
+/**
+ * A node having members.
+ * <p>
+ * The main reason for this interface is to permit users to manipulate homogeneously all nodes with a getMembers
+ * method.
+ */
+public interface NodeWithMembers<N extends Node> {
+    /**
+     * @return all members inside the braces of this node,
+     * like fields, methods, nested types, etc.
+     */
+    NodeList<BodyDeclaration<?>> getMembers();
+
+    void tryAddImportToParentCompilationUnit(Class<?> clazz);
+
+    default BodyDeclaration<?> getMember(int i) {
+        return getMembers().get(i);
+    }
+
+    @SuppressWarnings("unchecked")
+    default N setMember(int i, BodyDeclaration<?> member) {
+        getMembers().set(i, member);
+        return (N) this;
+    }
+
+    @SuppressWarnings("unchecked")
+    default N addMember(BodyDeclaration<?> member) {
+        getMembers().add(member);
+        return (N) this;
+    }
+
+    N setMembers(NodeList<BodyDeclaration<?>> members);
+
+    /**
+     * Add a field to this and automatically add the import of the type if needed
+     *
+     * @param typeClass the type of the field
+     * @param name the name of the field
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addField(Class<?> typeClass, String name, Modifier.Keyword... modifiers) {
+        tryAddImportToParentCompilationUnit(typeClass);
+        return addField(typeClass.getSimpleName(), name, modifiers);
+    }
+
+    /**
+     * Add a field to this.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addField(String type, String name, Modifier.Keyword... modifiers) {
+        return addField(parseType(type), name, modifiers);
+    }
+
+    /**
+     * Add a field to this.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addField(Type type, String name, Modifier.Keyword... modifiers) {
+        FieldDeclaration fieldDeclaration = new FieldDeclaration();
+        VariableDeclarator variable = new VariableDeclarator(type, name);
+        fieldDeclaration.getVariables().add(variable);
+        fieldDeclaration.setModifiers(createModifierList(modifiers));
+        getMembers().add(fieldDeclaration);
+        return fieldDeclaration;
+    }
+
+    /**
+     * Add a field to this and automatically add the import of the type if needed
+     *
+     * @param typeClass the type of the field
+     * @param name the name of the field
+     * @param initializer the initializer of the field
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addFieldWithInitializer(Class<?> typeClass, String name, Expression initializer, Modifier.Keyword... modifiers) {
+        tryAddImportToParentCompilationUnit(typeClass);
+        return addFieldWithInitializer(typeClass.getSimpleName(), name, initializer, modifiers);
+    }
+
+    /**
+     * Add a field to this.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @param initializer the initializer of the field
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addFieldWithInitializer(String type, String name, Expression initializer, Modifier.Keyword... modifiers) {
+        return addFieldWithInitializer(parseType(type), name, initializer, modifiers);
+    }
+
+    /**
+     * Add a field to this.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @param initializer the initializer of the field
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addFieldWithInitializer(Type type, String name, Expression initializer, Modifier.Keyword... modifiers) {
+        FieldDeclaration declaration = addField(type, name, modifiers);
+        declaration.getVariables().iterator().next().setInitializer(initializer);
+        return declaration;
+    }
+
+    /**
+     * Add a private field to this.
+     *
+     * @param typeClass the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addPrivateField(Class<?> typeClass, String name) {
+        return addField(typeClass, name, PRIVATE);
+    }
+
+    /**
+     * Add a private field to this and automatically add the import of the type if
+     * needed.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addPrivateField(String type, String name) {
+        return addField(type, name, PRIVATE);
+    }
+
+    /**
+     * Add a private field to this.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addPrivateField(Type type, String name) {
+        return addField(type, name, PRIVATE);
+    }
+
+    /**
+     * Add a public field to this.
+     *
+     * @param typeClass the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addPublicField(Class<?> typeClass, String name) {
+        return addField(typeClass, name, PUBLIC);
+    }
+
+    /**
+     * Add a public field to this and automatically add the import of the type if
+     * needed.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addPublicField(String type, String name) {
+        return addField(type, name, PUBLIC);
+    }
+
+    /**
+     * Add a public field to this.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addPublicField(Type type, String name) {
+        return addField(type, name, PUBLIC);
+    }
+
+    /**
+     * Add a protected field to this.
+     *
+     * @param typeClass the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addProtectedField(Class<?> typeClass, String name) {
+        return addField(typeClass, name, PROTECTED);
+    }
+
+    /**
+     * Add a protected field to this and automatically add the import of the type
+     * if needed.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addProtectedField(String type, String name) {
+        return addField(type, name, PROTECTED);
+    }
+
+    /**
+     * Add a protected field to this.
+     *
+     * @param type the type of the field
+     * @param name the name of the field
+     * @return the {@link FieldDeclaration} created
+     */
+    default FieldDeclaration addProtectedField(Type type, String name) {
+        return addField(type, name, PROTECTED);
+    }
+
+    /**
+     * Adds a methods with void return by default to this.
+     *
+     * @param methodName the method name
+     * @param modifiers the modifiers like {@link Modifier.Keyword#PUBLIC}
+     * @return the {@link MethodDeclaration} created
+     */
+    default MethodDeclaration addMethod(String methodName, Keyword... modifiers) {
+        MethodDeclaration methodDeclaration = new MethodDeclaration();
+        methodDeclaration.setName(methodName);
+        methodDeclaration.setType(new VoidType());
+        methodDeclaration.setModifiers(createModifierList(modifiers));
+        getMembers().add(methodDeclaration);
+        return methodDeclaration;
+    }
+
+    /**
+     * Add an initializer block ({@link InitializerDeclaration}) to this.
+     */
+    default BlockStmt addInitializer() {
+        BlockStmt block = new BlockStmt();
+        InitializerDeclaration initializerDeclaration = new InitializerDeclaration(false, block);
+        getMembers().add(initializerDeclaration);
+        return block;
+    }
+
+    /**
+     * Add a static initializer block ({@link InitializerDeclaration}) to this.
+     */
+    default BlockStmt addStaticInitializer() {
+        BlockStmt block = new BlockStmt();
+        InitializerDeclaration initializerDeclaration = new InitializerDeclaration(true, block);
+        getMembers().add(initializerDeclaration);
+        return block;
+    }
+
+    /**
+     * Try to find a {@link MethodDeclaration} by its name
+     *
+     * @param name the name of the method
+     * @return the methods found (multiple in case of overloading)
+     */
+    default List<MethodDeclaration> getMethodsByName(String name) {
+        return unmodifiableList(getMethods().stream()
+                .filter(m -> m.getNameAsString().equals(name))
+                .collect(toList()));
+    }
+
+    /**
+     * Find all methods in the members of this node.
+     *
+     * @return the methods found. This list is immutable.
+     */
+    default List<MethodDeclaration> getMethods() {
+        return unmodifiableList(getMembers().stream()
+                .filter(m -> m instanceof MethodDeclaration)
+                .map(m -> (MethodDeclaration) m)
+                .collect(toList()));
+    }
+
+    /**
+     * Try to find a {@link MethodDeclaration} by its parameters types
+     *
+     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void
+     * foo(Map&lt;Integer,String&gt; myMap,int number)
+     * @return the methods found (multiple in case of overloading)
+     */
+    default List<MethodDeclaration> getMethodsByParameterTypes(String... paramTypes) {
+        return unmodifiableList(getMethods().stream()
+                .filter(m -> m.hasParametersOfType(paramTypes))
+                .collect(toList()));
+    }
+
+    /**
+     * Try to find {@link MethodDeclaration}s by their name and parameters types
+     *
+     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void
+     * foo(Map&lt;Integer,String&gt; myMap,int number)
+     * @return the methods found (multiple in case of overloading)
+     */
+    default List<MethodDeclaration> getMethodsBySignature(String name, String... paramTypes) {
+        return unmodifiableList(getMethodsByName(name).stream()
+                .filter(m -> m.hasParametersOfType(paramTypes))
+                .collect(toList()));
+    }
+
+    /**
+     * Try to find a {@link MethodDeclaration} by its parameters types
+     *
+     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void
+     * foo(Map&lt;Integer,String&gt; myMap,int number)
+     * @return the methods found (multiple in case of overloading)
+     */
+    default List<MethodDeclaration> getMethodsByParameterTypes(Class<?>... paramTypes) {
+        return unmodifiableList(getMethods().stream()
+                .filter(m -> m.hasParametersOfType(paramTypes))
+                .collect(toList()));
+    }
+
+    /**
+     * Try to find a {@link FieldDeclaration} by its name
+     *
+     * @param name the name of the field
+     * @return null if not found, the FieldDeclaration otherwise
+     */
+    default Optional<FieldDeclaration> getFieldByName(String name) {
+        return getMembers().stream()
+                .filter(m -> m instanceof FieldDeclaration)
+                .map(f -> (FieldDeclaration) f)
+                .filter(f -> f.getVariables().stream()
+                        .anyMatch(var -> var.getNameAsString().equals(name)))
+                .findFirst();
+    }
+
+    /**
+     * Find all fields in the members of this node.
+     *
+     * @return the fields found. This list is immutable.
+     */
+    default List<FieldDeclaration> getFields() {
+        return unmodifiableList(getMembers().stream()
+                .filter(m -> m instanceof FieldDeclaration)
+                .map(m -> (FieldDeclaration) m)
+                .collect(toList()));
+    }
+
+    /**
+     * @return true if there are no members contained in this node.
+     */
+    default boolean isEmpty() {
+        return getMembers().isEmpty();
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java
index 3a499bf..c142315 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiers.java
@@ -21,13 +21,19 @@
 
 package com.github.javaparser.ast.nodeTypes;
 
+import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.resolution.declarations.HasAccessSpecifier;
 
 import java.util.Arrays;
-import java.util.EnumSet;
+import java.util.List;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
+import static com.github.javaparser.ast.NodeList.toNodeList;
+
 /**
  * A Node with Modifiers.
  * Note that not all modifiers may be valid for this node.
@@ -41,28 +47,34 @@
      * @return modifiers
      * @see Modifier
      */
-    EnumSet<Modifier> getModifiers();
+    NodeList<Modifier> getModifiers();
 
-    N setModifiers(EnumSet<Modifier> modifiers);
+    N setModifiers(NodeList<Modifier> modifiers);
 
     @SuppressWarnings("unchecked")
-    default N addModifier(Modifier... modifiers) {
-        EnumSet<Modifier> newModifiers = getModifiers().clone();
-        newModifiers.addAll(Arrays.stream(modifiers)
-                .collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))));
-        setModifiers(newModifiers);
+    default N addModifier(Modifier.Keyword... newModifiers) {
+        NodeList<Modifier> existingModifiers = new NodeList<>(getModifiers());
+        for (Modifier.Keyword newModifier : newModifiers) {
+            boolean alreadyPresent = existingModifiers.stream().anyMatch(m -> m.getKeyword() == newModifier);
+            if (!alreadyPresent) {
+                existingModifiers.add(new Modifier(newModifier));
+            }
+        }
+        setModifiers(existingModifiers);
         return (N) this;
     }
 
     @SuppressWarnings("unchecked")
-    default N removeModifier(Modifier... m) {
-        EnumSet<Modifier> newModifiers = getModifiers().clone();
-        newModifiers.removeAll(Arrays.stream(m)
-                .collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))));
-        setModifiers(newModifiers);
+    default N removeModifier(Modifier.Keyword... modifiersToRemove) {
+        List<Modifier.Keyword> modifiersToRemoveAsList = Arrays.asList(modifiersToRemove);
+        NodeList<Modifier> remaining = getModifiers().stream()
+                .filter(existingModifier -> !modifiersToRemoveAsList.contains(existingModifier.getKeyword()))
+                .collect(toNodeList());
+        setModifiers(remaining);
         return (N) this;
     }
-    default N setModifier(Modifier m, boolean set) {
+
+    default N setModifier(Modifier.Keyword m, boolean set) {
         if (set) {
             return addModifier(m);
         } else {
@@ -70,4 +82,37 @@
         }
     }
 
+    default boolean hasModifier(Modifier.Keyword modifier) {
+        for (Modifier m : getModifiers()) {
+            if (m.getKeyword() == modifier) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Creates a list of modifier nodes corresponding to the keywords passed, and set it.
+     */
+    default N setModifiers(final Modifier.Keyword... modifiers) {
+        return setModifiers(Arrays.stream(modifiers).map(Modifier::new).collect(toNodeList()));
+    }
+
+    /**
+     * @return the access specifier as far as it can be derived from the modifiers.
+     * Does not take anything else into account (like "interface methods are implicitly public")
+     */
+    default AccessSpecifier getAccessSpecifier() {
+        for (Modifier modifier : getModifiers()) {
+            switch (modifier.getKeyword()) {
+                case PUBLIC:
+                    return AccessSpecifier.PUBLIC;
+                case PROTECTED:
+                    return AccessSpecifier.PROTECTED;
+                case PRIVATE:
+                    return AccessSpecifier.PRIVATE;
+            }
+        }
+        return AccessSpecifier.PACKAGE_PRIVATE;
+    }
 }
\ No newline at end of file
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithName.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithName.java
index bc25cad..e2cd8c4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithName.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithName.java
@@ -24,7 +24,7 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.expr.Name;
 
-import static com.github.javaparser.JavaParser.parseName;
+import static com.github.javaparser.StaticJavaParser.parseName;
 import static com.github.javaparser.utils.Utils.assertNonEmpty;
 
 /**
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithParameters.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithParameters.java
index 517d8f5..a8e53ab 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithParameters.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithParameters.java
@@ -1,162 +1,162 @@
-/*

- * 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.nodeTypes;

-

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.NodeList;

-import com.github.javaparser.ast.body.Parameter;

-import com.github.javaparser.ast.type.Type;

-

-import java.util.Optional;

-import java.util.stream.Stream;

-

-import static com.github.javaparser.JavaParser.parseType;

-import static java.util.stream.Collectors.toSet;

-

-public interface NodeWithParameters<N extends Node> {

-    NodeList<Parameter> getParameters();

-

-    default Parameter getParameter(int i) {

-        return getParameters().get(i);

-    }

-

-    void tryAddImportToParentCompilationUnit(Class<?> clazz);

-

-    @SuppressWarnings("unchecked")

-    default N setParameter(int i, Parameter parameter) {

-        getParameters().set(i, parameter);

-        return (N) this;

-    }

-

-    N setParameters(NodeList<Parameter> parameters);

-

-    default N addParameter(Type type, String name) {

-        return addParameter(new Parameter(type, name));

-    }

-

-    default N addParameter(Class<?> paramClass, String name) {

-        tryAddImportToParentCompilationUnit(paramClass);

-        return addParameter(parseType(paramClass.getSimpleName()), name);

-    }

-

-    /**

-     * Remember to import the class in the compilation unit yourself

-     *

-     * @param className the name of the class, ex : org.test.Foo or Foo if you added manually the import

-     * @param name the name of the parameter

-     */

-    default N addParameter(String className, String name) {

-        return addParameter(parseType(className), name);

-    }

-

-    @SuppressWarnings("unchecked")

-    default N addParameter(Parameter parameter) {

-        getParameters().add(parameter);

-        return (N) this;

-    }

-

-    default Parameter addAndGetParameter(Type type, String name) {

-        return addAndGetParameter(new Parameter(type, name));

-    }

-

-    default Parameter addAndGetParameter(Class<?> paramClass, String name) {

-        tryAddImportToParentCompilationUnit(paramClass);

-        return addAndGetParameter(parseType(paramClass.getSimpleName()), name);

-    }

-

-    /**

-     * Remember to import the class in the compilation unit yourself

-     *

-     * @param className the name of the class, ex : org.test.Foo or Foo if you added manually the import

-     * @param name the name of the parameter

-     * @return the {@link Parameter} created

-     */

-    default Parameter addAndGetParameter(String className, String name) {

-        return addAndGetParameter(parseType(className), name);

-    }

-

-    default Parameter addAndGetParameter(Parameter parameter) {

-        getParameters().add(parameter);

-        return parameter;

-    }

-

-    /**

-     * Try to find a {@link Parameter} by its name

-     *

-     * @param name the name of the param

-     * @return null if not found, the param found otherwise

-     */

-    default Optional<Parameter> getParameterByName(String name) {

-        return getParameters().stream()

-                .filter(p -> p.getNameAsString().equals(name)).findFirst();

-    }

-

-    /**

-     * Try to find a {@link Parameter} by its type

-     *

-     * @param type the type of the param

-     * @return null if not found, the param found otherwise

-     */

-    default Optional<Parameter> getParameterByType(String type) {

-        return getParameters().stream()

-                .filter(p -> p.getType().toString().equals(type)).findFirst();

-    }

-

-    /**

-     * Try to find a {@link Parameter} by its type

-     *

-     * @param type the type of the param <b>take care about generics, it wont work</b>

-     * @return null if not found, the param found otherwise

-     */

-    default Optional<Parameter> getParameterByType(Class<?> type) {

-        return getParameters().stream()

-                .filter(p -> p.getType().toString().equals(type.getSimpleName())).findFirst();

-    }

-

-    /**

-     * Check if the parameters have certain types.

-     *

-     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void

-     * foo(Map&lt;Integer,String&gt; myMap,int number)

-     * @return true if all parameters match

-     */

-    default boolean hasParametersOfType(String... paramTypes) {

-        return getParameters().stream()

-                .map(p -> p.getType().toString())

-                .collect(toSet())

-                .equals(Stream.of(paramTypes).collect(toSet()));

-    }

-

-    /**

-     * Check if the parameters have certain types. Note that this is a match in SimpleName, so "java.awt.List" and

-     * "java.util.List" are identical to this algorithm.

-     *

-     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void

-     * foo(Map&lt;Integer,String&gt; myMap,int number)

-     * @return true if all parameters match

-     */

-    default boolean hasParametersOfType(Class<?>... paramTypes) {

-        return getParameters().stream().map(p -> p.getType().toString())

-                .collect(toSet())

-                .equals(Stream.of(paramTypes).map(Class::getSimpleName).collect(toSet()));

-    }

-}

+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.type.Type;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static com.github.javaparser.StaticJavaParser.parseType;
+import static java.util.stream.Collectors.toSet;
+
+public interface NodeWithParameters<N extends Node> {
+    NodeList<Parameter> getParameters();
+
+    default Parameter getParameter(int i) {
+        return getParameters().get(i);
+    }
+
+    void tryAddImportToParentCompilationUnit(Class<?> clazz);
+
+    @SuppressWarnings("unchecked")
+    default N setParameter(int i, Parameter parameter) {
+        getParameters().set(i, parameter);
+        return (N) this;
+    }
+
+    N setParameters(NodeList<Parameter> parameters);
+
+    default N addParameter(Type type, String name) {
+        return addParameter(new Parameter(type, name));
+    }
+
+    default N addParameter(Class<?> paramClass, String name) {
+        tryAddImportToParentCompilationUnit(paramClass);
+        return addParameter(parseType(paramClass.getSimpleName()), name);
+    }
+
+    /**
+     * Remember to import the class in the compilation unit yourself
+     *
+     * @param className the name of the class, ex : org.test.Foo or Foo if you added manually the import
+     * @param name the name of the parameter
+     */
+    default N addParameter(String className, String name) {
+        return addParameter(parseType(className), name);
+    }
+
+    @SuppressWarnings("unchecked")
+    default N addParameter(Parameter parameter) {
+        getParameters().add(parameter);
+        return (N) this;
+    }
+
+    default Parameter addAndGetParameter(Type type, String name) {
+        return addAndGetParameter(new Parameter(type, name));
+    }
+
+    default Parameter addAndGetParameter(Class<?> paramClass, String name) {
+        tryAddImportToParentCompilationUnit(paramClass);
+        return addAndGetParameter(parseType(paramClass.getSimpleName()), name);
+    }
+
+    /**
+     * Remember to import the class in the compilation unit yourself
+     *
+     * @param className the name of the class, ex : org.test.Foo or Foo if you added manually the import
+     * @param name the name of the parameter
+     * @return the {@link Parameter} created
+     */
+    default Parameter addAndGetParameter(String className, String name) {
+        return addAndGetParameter(parseType(className), name);
+    }
+
+    default Parameter addAndGetParameter(Parameter parameter) {
+        getParameters().add(parameter);
+        return parameter;
+    }
+
+    /**
+     * Try to find a {@link Parameter} by its name
+     *
+     * @param name the name of the param
+     * @return null if not found, the param found otherwise
+     */
+    default Optional<Parameter> getParameterByName(String name) {
+        return getParameters().stream()
+                .filter(p -> p.getNameAsString().equals(name)).findFirst();
+    }
+
+    /**
+     * Try to find a {@link Parameter} by its type
+     *
+     * @param type the type of the param
+     * @return null if not found, the param found otherwise
+     */
+    default Optional<Parameter> getParameterByType(String type) {
+        return getParameters().stream()
+                .filter(p -> p.getType().toString().equals(type)).findFirst();
+    }
+
+    /**
+     * Try to find a {@link Parameter} by its type
+     *
+     * @param type the type of the param <b>take care about generics, it wont work</b>
+     * @return null if not found, the param found otherwise
+     */
+    default Optional<Parameter> getParameterByType(Class<?> type) {
+        return getParameters().stream()
+                .filter(p -> p.getType().toString().equals(type.getSimpleName())).findFirst();
+    }
+
+    /**
+     * Check if the parameters have certain types.
+     *
+     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void
+     * foo(Map&lt;Integer,String&gt; myMap,int number)
+     * @return true if all parameters match
+     */
+    default boolean hasParametersOfType(String... paramTypes) {
+        return getParameters().stream()
+                .map(p -> p.getType().toString())
+                .collect(toSet())
+                .equals(Stream.of(paramTypes).collect(toSet()));
+    }
+
+    /**
+     * Check if the parameters have certain types. Note that this is a match in SimpleName, so "java.awt.List" and
+     * "java.util.List" are identical to this algorithm.
+     *
+     * @param paramTypes the types of parameters like "Map&lt;Integer,String&gt;","int" to match<br> void
+     * foo(Map&lt;Integer,String&gt; myMap,int number)
+     * @return true if all parameters match
+     */
+    default boolean hasParametersOfType(Class<?>... paramTypes) {
+        return getParameters().stream().map(p -> p.getType().toString())
+                .collect(toSet())
+                .equals(Stream.of(paramTypes).map(Class::getSimpleName).collect(toSet()));
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithRange.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithRange.java
index d1e2fb7..119a500 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithRange.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithRange.java
@@ -8,7 +8,6 @@
 
 /**
  * A node that has a Range, which is every Node.
- * 
  */
 public interface NodeWithRange<N> {
     Optional<Range> getRange();
@@ -29,26 +28,31 @@
         return getRange().map(r -> r.end);
     }
 
+    /**
+     * @deprecated use {@link #containsWithinRange(Node)} instead.
+     */
+    @Deprecated
     default boolean containsWithin(Node other) {
+        return containsWithinRange(other);
+    }
+
+    /**
+     * Checks whether the range of the given {@code Node} is contained within the range of this {@code NodeWithRange}.
+     * Note that any range contains itself, i.e., for any node {@code n}, we have that
+     * {@code n.containsWithinRange(n) == true}.
+     *
+     * <b>Notice:</b> This method compares two nodes based on their ranges <i>only</i>, but <i>not</i> based on the
+     * storage unit of the two nodes. Therefore, this method may return {@code true} for a node that is contained in a
+     * different file than this {@code NodeWithRange}. You may wish to use {@link Node#isAncestorOf(Node)} instead.
+     *
+     * @param other the node whose range should be compared with this node's range.
+     * @return {@code true} if the given node's range is contained within this node's range, and {@code false}
+     * otherwise.
+     */
+    default boolean containsWithinRange(Node other) {
         if (getRange().isPresent() && other.getRange().isPresent()) {
             return getRange().get().contains(other.getRange().get());
         }
         return false;
     }
-
-    /**
-     * @deprecated use isAfter() on range
-     */
-    @Deprecated
-    default boolean isPositionedAfter(Position position) {
-        return getRange().map(r -> r.isAfter(position)).orElse(false);
-    }
-
-    /**
-     * @deprecated use isBefore() on range
-     */
-    @Deprecated
-    default boolean isPositionedBefore(Position position) {
-        return getRange().map(r -> r.isBefore(position)).orElse(false);
-    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithStatements.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithStatements.java
index 4d2c90c..3e3aeb7 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithStatements.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithStatements.java
@@ -1,114 +1,117 @@
-/*

- * 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.nodeTypes;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.NodeList;

-import com.github.javaparser.ast.expr.Expression;

-import com.github.javaparser.ast.expr.NameExpr;

-import com.github.javaparser.ast.stmt.ExpressionStmt;

-import com.github.javaparser.ast.stmt.Statement;

-

-import static com.github.javaparser.JavaParser.*;

-

-/**

- * A node that contains a list of statements.

- */

-public interface NodeWithStatements<N extends Node> {

-    NodeList<Statement> getStatements();

-

-    default Statement getStatement(int i) {

-        return getStatements().get(i);

-    }

-

-    @SuppressWarnings("unchecked")

-    default N setStatement(int i, Statement statement) {

-        getStatements().set(i, statement);

-        return (N) this;

-    }

-

-    N setStatements(final NodeList<Statement> statements);

-

-    @SuppressWarnings("unchecked")

-    default N addStatement(Statement statement) {

-        getStatements().add(statement);

-        return (N) this;

-    }

-

-    @SuppressWarnings("unchecked")

-    default N addStatement(int index, final Statement statement) {

-        getStatements().add(index, statement);

-        return (N) this;

-    }

-

-    default N addStatement(Expression expr) {

-        return addStatement(new ExpressionStmt(expr));

-    }

-

-    /**

-     * It will use {@link JavaParser#parseStatement(String)} inside, so it should end with a semi column

-     */

-    default N addStatement(String statement) {

-        return addStatement(parseStatement(statement));

-    }

-

-    default N addStatement(int index, final Expression expr) {

-        Statement stmt = new ExpressionStmt(expr);

-        return addStatement(index, stmt);

-    }

-

-    default <A extends Statement> A addAndGetStatement(A statement) {

-        getStatements().add(statement);

-        return statement;

-    }

-

-    default Statement addAndGetStatement(int index, final Statement statement) {

-        getStatements().add(index, statement);

-        return statement;

-    }

-

-    default ExpressionStmt addAndGetStatement(Expression expr) {

-        ExpressionStmt statement = new ExpressionStmt(expr);

-        return addAndGetStatement(statement);

-    }

-

-    default ExpressionStmt addAndGetStatement(String statement) {

-        return addAndGetStatement(new NameExpr(statement));

-    }

-

-    default boolean isEmpty() {

-        return getStatements().isEmpty();

-    }

-

-    @SuppressWarnings("unchecked")

-    default N copyStatements(NodeList<Statement> nodeList) {

-        for (Statement n : nodeList) {

-            addStatement(n.clone());

-        }

-        return (N) this;

-    }

-

-    default N copyStatements(NodeWithStatements<?> other) {

-        return copyStatements(other.getStatements());

-    }

-}

+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.Statement;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+
+/**
+ * A node that contains a list of statements.
+ */
+public interface NodeWithStatements<N extends Node> {
+    NodeList<Statement> getStatements();
+
+    default Statement getStatement(int i) {
+        return getStatements().get(i);
+    }
+
+    @SuppressWarnings("unchecked")
+    default N setStatement(int i, Statement statement) {
+        getStatements().set(i, statement);
+        return (N) this;
+    }
+
+    N setStatements(final NodeList<Statement> statements);
+
+    @SuppressWarnings("unchecked")
+    default N addStatement(Statement statement) {
+        getStatements().add(statement);
+        return (N) this;
+    }
+
+    @SuppressWarnings("unchecked")
+    default N addStatement(int index, final Statement statement) {
+        getStatements().add(index, statement);
+        return (N) this;
+    }
+
+    default N addStatement(Expression expr) {
+        return addStatement(new ExpressionStmt(expr));
+    }
+
+    /**
+     * It will use {@link JavaParser#parseStatement(String)} inside, so it should end with a semicolon
+     */
+    default N addStatement(String statement) {
+        return addStatement(parseStatement(statement));
+    }
+
+    default N addStatement(int index, final Expression expr) {
+        Statement stmt = new ExpressionStmt(expr);
+        return addStatement(index, stmt);
+    }
+
+    default <A extends Statement> A addAndGetStatement(A statement) {
+        getStatements().add(statement);
+        return statement;
+    }
+
+    default Statement addAndGetStatement(int index, final Statement statement) {
+        getStatements().add(index, statement);
+        return statement;
+    }
+
+    default ExpressionStmt addAndGetStatement(Expression expr) {
+        ExpressionStmt statement = new ExpressionStmt(expr);
+        return addAndGetStatement(statement);
+    }
+
+    default ExpressionStmt addAndGetStatement(String statement) {
+        return addAndGetStatement(new NameExpr(statement));
+    }
+
+    /**
+     * @return true if there are no statements contained in this node.
+     */
+    default boolean isEmpty() {
+        return getStatements().isEmpty();
+    }
+
+    @SuppressWarnings("unchecked")
+    default N copyStatements(NodeList<Statement> nodeList) {
+        for (Statement n : nodeList) {
+            addStatement(n.clone());
+        }
+        return (N) this;
+    }
+
+    default N copyStatements(NodeWithStatements<?> other) {
+        return copyStatements(other.getStatements());
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithThrownExceptions.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithThrownExceptions.java
index e1b9007..a7ebc7b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithThrownExceptions.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithThrownExceptions.java
@@ -25,7 +25,7 @@
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.type.ReferenceType;
 
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
+import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
 
 /**
  * A node that declares the types of exception it throws.
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithType.java
index 06e66fb..a54a4fd 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithType.java
@@ -1,78 +1,78 @@
-/*

- * 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.nodeTypes;

-

-import com.github.javaparser.ast.CompilationUnit;

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.type.Type;

-

-import static com.github.javaparser.JavaParser.parseType;

-import static com.github.javaparser.utils.Utils.assertNonEmpty;

-

-/**

- * A node with a type.

- * <p>

- * The main reason for this interface is to permit users to manipulate homogeneously all nodes with getType/setType

- * methods

- *

- * @since 2.3.1

- */

-public interface NodeWithType<N extends Node, T extends Type> {

-    /**

-     * Gets the type

-     *

-     * @return the type

-     */

-    T getType();

-

-    /**

-     * Sets the type

-     *

-     * @param type the type

-     * @return this

-     */

-    N setType(T type);

-

-    void tryAddImportToParentCompilationUnit(Class<?> clazz);

-

-    /**

-     * Sets this type to this class and try to import it to the {@link CompilationUnit} if needed

-     *

-     * @param typeClass the type

-     * @return this

-     */

-    @SuppressWarnings("unchecked")

-    default N setType(Class<?> typeClass) {

-        tryAddImportToParentCompilationUnit(typeClass);

-        return setType((T) parseType(typeClass.getSimpleName()));

-    }

-

-    @SuppressWarnings("unchecked")

-    default N setType(final String typeString) {

-        assertNonEmpty(typeString);

-        return setType((T) parseType(typeString));

-    }

-

-    default String getTypeAsString() {

-        return getType().asString();

-    }

-}

+/*
+ * 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.nodeTypes;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.type.Type;
+
+import static com.github.javaparser.StaticJavaParser.parseType;
+import static com.github.javaparser.utils.Utils.assertNonEmpty;
+
+/**
+ * A node with a type.
+ * <p>
+ * The main reason for this interface is to permit users to manipulate homogeneously all nodes with getType/setType
+ * methods
+ *
+ * @since 2.3.1
+ */
+public interface NodeWithType<N extends Node, T extends Type> {
+    /**
+     * Gets the type
+     *
+     * @return the type
+     */
+    T getType();
+
+    /**
+     * Sets the type
+     *
+     * @param type the type
+     * @return this
+     */
+    N setType(T type);
+
+    void tryAddImportToParentCompilationUnit(Class<?> clazz);
+
+    /**
+     * Sets this type to this class and try to import it to the {@link CompilationUnit} if needed
+     *
+     * @param typeClass the type
+     * @return this
+     */
+    @SuppressWarnings("unchecked")
+    default N setType(Class<?> typeClass) {
+        tryAddImportToParentCompilationUnit(typeClass);
+        return setType((T) parseType(typeClass.getSimpleName()));
+    }
+
+    @SuppressWarnings("unchecked")
+    default N setType(final String typeString) {
+        assertNonEmpty(typeString);
+        return setType((T) parseType(typeString));
+    }
+
+    default String getTypeAsString() {
+        return getType().asString();
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeArguments.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeArguments.java
index 0c72b22..d2b4a82 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeArguments.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeArguments.java
@@ -38,6 +38,8 @@
  *     new X&lt;>();      --> typeArguments = [], diamondOperator = true
  *     new X&lt;C,D>();   --> typeArguments = [C,D], diamondOperator = false
  * </pre>
+ * Only ObjectCreationExpr uses the diamond operator.
+ * On other nodes it is treated the same as the first case.
  */
 public interface NodeWithTypeArguments<N extends Node> {
     /**
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeParameters.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeParameters.java
index 8817a76..5957815 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeParameters.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithTypeParameters.java
@@ -25,6 +25,8 @@
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.type.TypeParameter;
 
+import static com.github.javaparser.StaticJavaParser.parseTypeParameter;
+
 /**
  * A node that can have type parameters.
  * <pre>
@@ -52,6 +54,13 @@
         return (N) this;
     }
 
+    /**
+     * Adds a type parameter like "X extends Serializable"
+     */
+    default N addTypeParameter(String typeParameter) {
+        return addTypeParameter(parseTypeParameter(typeParameter));
+    }
+
     N setTypeParameters(NodeList<TypeParameter> typeParameters);
 
     default boolean isGeneric() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithVariables.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithVariables.java
index 5daf38a..311e4ba 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithVariables.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/NodeWithVariables.java
@@ -101,6 +101,19 @@
     }
 
     /**
+     * Sets the type of all variables.
+     * Erases any existing type.
+     * This is a shortcut for setting a type on all variable declarators separately.
+     */
+    @SuppressWarnings("unchecked")
+    default N setAllTypes(Type newType) {
+        for (VariableDeclarator variable : getVariables()) {
+            variable.setType(newType);
+        }
+        return (N) this;
+    }
+
+    /**
      * Returns the type that maximum shared type between all variables.
      * The minimum common type does never include annotations on the array level.
      * <p>
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/SwitchNode.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/SwitchNode.java
new file mode 100644
index 0000000..1c313f2
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/SwitchNode.java
@@ -0,0 +1,43 @@
+package com.github.javaparser.ast.nodeTypes;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.comments.Comment;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.SwitchEntry;
+
+import java.util.Optional;
+
+/**
+ * The common interface of {@link com.github.javaparser.ast.expr.SwitchExpr} and {@link com.github.javaparser.ast.stmt.SwitchStmt}
+ */
+public interface SwitchNode {
+    NodeList<SwitchEntry> getEntries();
+
+    SwitchEntry getEntry(int i);
+
+    Expression getSelector();
+
+    SwitchNode setEntries(NodeList<SwitchEntry> entries);
+
+    SwitchNode setSelector(Expression selector);
+
+    boolean remove(Node node);
+
+    SwitchNode clone();
+
+    boolean replace(Node node, Node replacementNode);
+
+    Optional<Comment> getComment();
+
+    /**
+     * @return true if there are no labels or anything contained in this switch.
+     */
+    default boolean isEmpty() {
+        return getEntries().isEmpty();
+    }
+
+
+    // Too bad Node isn't an interface, or this could have easily inherited all of its methods.
+    // Add more when required.
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithAbstractModifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithAbstractModifier.java
index c81c4c6..0f916fa 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithAbstractModifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithAbstractModifier.java
@@ -3,14 +3,14 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 
-import static com.github.javaparser.ast.Modifier.ABSTRACT;
+import static com.github.javaparser.ast.Modifier.Keyword.ABSTRACT;
 
 /**
  * A node that can be abstract.
  */
 public interface NodeWithAbstractModifier<N extends Node> extends NodeWithModifiers<N> {
     default boolean isAbstract() {
-        return getModifiers().contains(ABSTRACT);
+        return hasModifier(ABSTRACT);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithFinalModifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithFinalModifier.java
index 91aae40..e3111e0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithFinalModifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithFinalModifier.java
@@ -3,14 +3,14 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 
-import static com.github.javaparser.ast.Modifier.FINAL;
+import static com.github.javaparser.ast.Modifier.Keyword.FINAL;
 
 /**
  * A node that can be final.
  */
 public interface NodeWithFinalModifier<N extends Node> extends NodeWithModifiers<N> {
     default boolean isFinal() {
-        return getModifiers().contains(FINAL);
+        return hasModifier(FINAL);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPrivateModifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPrivateModifier.java
index 4aa022c..620e2af 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPrivateModifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPrivateModifier.java
@@ -3,14 +3,14 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 
-import static com.github.javaparser.ast.Modifier.*;
+import static com.github.javaparser.ast.Modifier.Keyword.PRIVATE;
 
 /**
  * A node that can be private.
  */
 public interface NodeWithPrivateModifier<N extends Node> extends NodeWithModifiers<N> {
     default boolean isPrivate() {
-        return getModifiers().contains(PRIVATE);
+        return hasModifier(PRIVATE);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithProtectedModifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithProtectedModifier.java
index d2200b7..b9161b7 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithProtectedModifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithProtectedModifier.java
@@ -3,14 +3,14 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 
-import static com.github.javaparser.ast.Modifier.*;
+import static com.github.javaparser.ast.Modifier.Keyword.PROTECTED;
 
 /**
  * A node that can be protected.
  */
 public interface NodeWithProtectedModifier<N extends Node> extends NodeWithModifiers<N> {
     default boolean isProtected() {
-        return getModifiers().contains(PROTECTED);
+        return hasModifier(PROTECTED);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPublicModifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPublicModifier.java
index 64b4067..a4a366c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPublicModifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithPublicModifier.java
@@ -3,14 +3,14 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 
-import static com.github.javaparser.ast.Modifier.*;
+import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC;
 
 /**
  * A node that can be public.
  */
 public interface NodeWithPublicModifier<N extends Node> extends NodeWithModifiers<N> {
     default boolean isPublic() {
-        return getModifiers().contains(PUBLIC);
+        return hasModifier(PUBLIC);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStaticModifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStaticModifier.java
index 5ac63ea..34445f3 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStaticModifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStaticModifier.java
@@ -3,7 +3,7 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 
-import static com.github.javaparser.ast.Modifier.STATIC;
+import static com.github.javaparser.ast.Modifier.Keyword.STATIC;
 
 /**
  * A node that can be static.
@@ -11,7 +11,7 @@
 public interface NodeWithStaticModifier<N extends Node> extends NodeWithModifiers<N> {
 
     default boolean isStatic() {
-        return getModifiers().contains(STATIC);
+        return hasModifier(STATIC);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStrictfpModifier.java b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStrictfpModifier.java
index 1d8fb41..7db7a4d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStrictfpModifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/nodeTypes/modifiers/NodeWithStrictfpModifier.java
@@ -3,14 +3,14 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 
-import static com.github.javaparser.ast.Modifier.STRICTFP;
+import static com.github.javaparser.ast.Modifier.Keyword.STRICTFP;
 
 /**
  * A node that can be strictfp.
  */
 public interface NodeWithStrictfpModifier<N extends Node> extends NodeWithModifiers<N> {
     default boolean isStrictfp() {
-        return getModifiers().contains(STRICTFP);
+        return hasModifier(STRICTFP);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java
index d7f82f3..e644503 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java
@@ -22,12 +22,12 @@
 
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.Generated;
 import com.github.javaparser.utils.Utils;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
 import java.util.Optional;
 import java.util.Arrays;
-import javax.annotation.Generated;
 
 /**
  * Properties considered by the AstObserver
@@ -44,7 +44,6 @@
     CHECK(Type.SINGLE_REFERENCE),
     CLASS_BODY(Type.MULTIPLE_REFERENCE),
     CLASS_DECLARATION(Type.SINGLE_REFERENCE),
-    CLASS_EXPR(Type.SINGLE_REFERENCE),
     COMMENT(Type.SINGLE_REFERENCE),
     COMPARE(Type.SINGLE_REFERENCE),
     COMPONENT_TYPE(Type.SINGLE_REFERENCE),
@@ -52,6 +51,7 @@
     CONTENT(Type.SINGLE_ATTRIBUTE),
     DEFAULT_VALUE(Type.SINGLE_REFERENCE),
     DIMENSION(Type.SINGLE_REFERENCE),
+    DIRECTIVES(Type.MULTIPLE_REFERENCE),
     ELEMENTS(Type.MULTIPLE_REFERENCE),
     ELEMENT_TYPE(Type.SINGLE_REFERENCE),
     ELSE_EXPR(Type.SINGLE_REFERENCE),
@@ -71,16 +71,17 @@
     INNER(Type.SINGLE_REFERENCE),
     INTERFACE(Type.SINGLE_ATTRIBUTE),
     ITERABLE(Type.SINGLE_REFERENCE),
+    KEYWORD(Type.SINGLE_ATTRIBUTE),
     LABEL(Type.SINGLE_REFERENCE),
+    LABELS(Type.MULTIPLE_REFERENCE),
     LEFT(Type.SINGLE_REFERENCE),
     LEVELS(Type.MULTIPLE_REFERENCE),
     MEMBERS(Type.MULTIPLE_REFERENCE),
     MEMBER_VALUE(Type.SINGLE_REFERENCE),
     MESSAGE(Type.SINGLE_REFERENCE),
-    MODIFIERS(Type.MULTIPLE_ATTRIBUTE),
+    MODIFIERS(Type.MULTIPLE_REFERENCE),
     MODULE(Type.SINGLE_REFERENCE),
     MODULE_NAMES(Type.MULTIPLE_REFERENCE),
-    MODULE_STMTS(Type.MULTIPLE_REFERENCE),
     NAME(Type.SINGLE_REFERENCE),
     OPEN(Type.SINGLE_ATTRIBUTE),
     OPERATOR(Type.SINGLE_ATTRIBUTE),
@@ -109,6 +110,7 @@
     TYPES(Type.MULTIPLE_REFERENCE),
     TYPE_ARGUMENTS(Type.MULTIPLE_REFERENCE),
     TYPE_BOUND(Type.MULTIPLE_REFERENCE),
+    TYPE_NAME(Type.SINGLE_REFERENCE),
     TYPE_PARAMETERS(Type.MULTIPLE_REFERENCE),
     UPDATE(Type.MULTIPLE_REFERENCE),
     VALUE(Type.SINGLE_REFERENCE),
@@ -117,7 +119,7 @@
     VARIABLES(Type.MULTIPLE_REFERENCE),
     VAR_ARGS(Type.SINGLE_ATTRIBUTE),
     VAR_ARGS_ANNOTATIONS(Type.MULTIPLE_REFERENCE),
-    WITH_TYPES(Type.MULTIPLE_REFERENCE),
+    WITH(Type.MULTIPLE_REFERENCE),
     CASCADING_IF_STMT(Type.SINGLE_ATTRIBUTE, true),
     ELSE_BLOCK(Type.SINGLE_ATTRIBUTE, true),
     ELSE_BRANCH(Type.SINGLE_ATTRIBUTE, true),
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/AssertStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/AssertStmt.java
index a6eb59f..1fd8f51 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/AssertStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/AssertStmt.java
@@ -32,17 +32,17 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.AssertStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A usage of the keyword "assert"
  * <br/>In <code>assert dead : "Wasn't expecting to be dead here";</code> the check is "dead" and the message is the string.
  * @author Julio Vilmar Gesser
  */
-public final class AssertStmt extends Statement {
+public class AssertStmt extends Statement {
 
     private Expression check;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BlockStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BlockStmt.java
index 3e25b96..e28bdd4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BlockStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BlockStmt.java
@@ -26,24 +26,22 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 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.BlockStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Statements in between { and }.
  *
  * @author Julio Vilmar Gesser
  */
-public final class BlockStmt extends Statement implements NodeWithStatements<BlockStmt> {
+public class BlockStmt extends Statement implements NodeWithStatements<BlockStmt> {
 
     private NodeList<Statement> statements;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BreakStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BreakStmt.java
index 4a0b411..640eed0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BreakStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/BreakStmt.java
@@ -20,52 +20,64 @@
  */
 package com.github.javaparser.ast.stmt;
 
+import com.github.javaparser.TokenRange;
 import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.ast.Generated;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.NameExpr;
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
+import com.github.javaparser.metamodel.OptionalProperty;
 import java.util.Optional;
+import java.util.function.Consumer;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.BreakStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import com.github.javaparser.metamodel.OptionalProperty;
-import java.util.function.Consumer;
 
 /**
- * A usage of the break keyword.
- * <br/>In <code>break abc;</code> the label is abc.
+ * <h1>The break statement</h1>
+ * <h2>Java 1.0-11</h2>
+ * Break has an optional label:
+ * <br/><code>break;</code>
+ * <br/><code>break somewhere;</code>
+ * <br/>The label is in the "value" property as a NameExpr.
+ * <h2>Java 12</h2>
+ * Break can now also have any expression,
+ * to be used in the switch-expression:
+ * <br/><code>break 123+456;</code>
+ * <br/><code>break "more or less";</code>
+ * <br/>The expression will be in the "value" property.
  *
  * @author Julio Vilmar Gesser
+ * @see com.github.javaparser.ast.expr.SwitchExpr
  */
-public final class BreakStmt extends Statement {
+public class BreakStmt extends Statement {
 
     @OptionalProperty
-    private SimpleName label;
+    private Expression value;
 
     public BreakStmt() {
-        this(null, new SimpleName());
+        this(null, new NameExpr());
     }
 
     public BreakStmt(final String label) {
-        this(null, new SimpleName(label));
+        this(null, new NameExpr(label));
     }
 
     @AllFieldsConstructor
-    public BreakStmt(final SimpleName label) {
-        this(null, label);
+    public BreakStmt(final Expression value) {
+        this(null, value);
     }
 
     /**
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public BreakStmt(TokenRange tokenRange, SimpleName label) {
+    public BreakStmt(TokenRange tokenRange, Expression value) {
         super(tokenRange);
-        setLabel(label);
+        setValue(value);
         customInitialization();
     }
 
@@ -82,26 +94,26 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Optional<SimpleName> getLabel() {
-        return Optional.ofNullable(label);
+    public Optional<Expression> getValue() {
+        return Optional.ofNullable(value);
     }
 
     /**
      * Sets the label
      *
-     * @param label the label, can be null
+     * @param value the label or the expression, can be null
      * @return this, the BreakStmt
      */
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public BreakStmt setLabel(final SimpleName label) {
-        if (label == this.label) {
+    public BreakStmt setValue(final Expression value) {
+        if (value == this.value) {
             return (BreakStmt) this;
         }
-        notifyPropertyChange(ObservableProperty.LABEL, this.label, label);
-        if (this.label != null)
-            this.label.setParentNode(null);
-        this.label = label;
-        setAsParentNodeOf(label);
+        notifyPropertyChange(ObservableProperty.VALUE, this.value, value);
+        if (this.value != null)
+            this.value.setParentNode(null);
+        this.value = value;
+        setAsParentNodeOf(value);
         return this;
     }
 
@@ -110,9 +122,9 @@
     public boolean remove(Node node) {
         if (node == null)
             return false;
-        if (label != null) {
-            if (node == label) {
-                removeLabel();
+        if (value != null) {
+            if (node == value) {
+                removeValue();
                 return true;
             }
         }
@@ -120,8 +132,8 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public BreakStmt removeLabel() {
-        return setLabel((SimpleName) null);
+    public BreakStmt removeValue() {
+        return setValue((Expression) null);
     }
 
     @Override
@@ -141,9 +153,9 @@
     public boolean replace(Node node, Node replacementNode) {
         if (node == null)
             return false;
-        if (label != null) {
-            if (node == label) {
-                setLabel((SimpleName) replacementNode);
+        if (value != null) {
+            if (node == value) {
+                setValue((Expression) replacementNode);
                 return true;
             }
         }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/CatchClause.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/CatchClause.java
index 9eaa30e..2532a13 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/CatchClause.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/CatchClause.java
@@ -20,25 +20,22 @@
  */
 package com.github.javaparser.ast.stmt;
 
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.body.Parameter;
 import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.expr.SimpleName;
 import com.github.javaparser.ast.nodeTypes.NodeWithBlockStmt;
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.EnumSet;
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.CatchClauseMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The catch part of a try-catch-finally. <br/>In <code>try { ... } catch (Exception e) { ... }</code> the CatchClause
@@ -46,7 +43,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class CatchClause extends Node implements NodeWithBlockStmt<CatchClause> {
+public class CatchClause extends Node implements NodeWithBlockStmt<CatchClause> {
 
     private Parameter parameter;
 
@@ -56,7 +53,7 @@
         this(null, new Parameter(), new BlockStmt());
     }
 
-    public CatchClause(final EnumSet<Modifier> exceptModifier, final NodeList<AnnotationExpr> exceptAnnotations, final ClassOrInterfaceType exceptType, final SimpleName exceptName, final BlockStmt body) {
+    public CatchClause(final NodeList<Modifier> exceptModifier, final NodeList<AnnotationExpr> exceptAnnotations, final ClassOrInterfaceType exceptType, final SimpleName exceptName, final BlockStmt body) {
         this(null, new Parameter(null, exceptModifier, exceptAnnotations, exceptType, false, new NodeList<>(), exceptName), body);
     }
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ContinueStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ContinueStmt.java
index b829950..f674cb3 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ContinueStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ContinueStmt.java
@@ -31,10 +31,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ContinueStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A continue statement with an optional label;
@@ -43,7 +43,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ContinueStmt extends Statement implements NodeWithOptionalLabel<ContinueStmt> {
+public class ContinueStmt extends Statement implements NodeWithOptionalLabel<ContinueStmt> {
 
     @OptionalProperty
     private SimpleName label;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/DoStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/DoStmt.java
index 7c161ff..a805ac6 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/DoStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/DoStmt.java
@@ -33,10 +33,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.DoStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A do-while.
@@ -44,7 +44,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class DoStmt extends Statement implements NodeWithBody<DoStmt>, NodeWithCondition<DoStmt> {
+public class DoStmt extends Statement implements NodeWithBody<DoStmt>, NodeWithCondition<DoStmt> {
 
     private Statement body;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/EmptyStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/EmptyStmt.java
index d73ede6..99bdbed 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/EmptyStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/EmptyStmt.java
@@ -28,15 +28,15 @@
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.metamodel.EmptyStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An empty statement is a ";" where a statement is expected.
  * @author Julio Vilmar Gesser
  */
-public final class EmptyStmt extends Statement {
+public class EmptyStmt extends Statement {
 
     @AllFieldsConstructor
     public EmptyStmt() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExplicitConstructorInvocationStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExplicitConstructorInvocationStmt.java
index 2b9b9c2..df9e438 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExplicitConstructorInvocationStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExplicitConstructorInvocationStmt.java
@@ -22,25 +22,26 @@
 
 import com.github.javaparser.ast.AllFieldsConstructor;
 import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.nodeTypes.NodeWithArguments;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
 import com.github.javaparser.ast.observer.ObservableProperty;
 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;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ExplicitConstructorInvocationStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
+import com.github.javaparser.resolution.Resolvable;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A call to super or this in a constructor or initializer.
@@ -51,7 +52,7 @@
  * @see com.github.javaparser.ast.expr.SuperExpr
  * @see com.github.javaparser.ast.expr.ThisExpr
  */
-public final class ExplicitConstructorInvocationStmt extends Statement implements NodeWithTypeArguments<ExplicitConstructorInvocationStmt> {
+public class ExplicitConstructorInvocationStmt extends Statement implements NodeWithTypeArguments<ExplicitConstructorInvocationStmt>, NodeWithArguments<ExplicitConstructorInvocationStmt>, Resolvable<ResolvedConstructorDeclaration> {
 
     @OptionalProperty
     private NodeList<Type> typeArguments;
@@ -64,11 +65,11 @@
     private NodeList<Expression> arguments;
 
     public ExplicitConstructorInvocationStmt() {
-        this(null, new NodeList<>(), true, null, new NodeList<>());
+        this(null, null, true, null, new NodeList<>());
     }
 
     public ExplicitConstructorInvocationStmt(final boolean isThis, final Expression expression, final NodeList<Expression> arguments) {
-        this(null, new NodeList<>(), isThis, expression, arguments);
+        this(null, null, isThis, expression, arguments);
     }
 
     @AllFieldsConstructor
@@ -106,20 +107,6 @@
         return arguments;
     }
 
-    public Expression getArgument(int i) {
-        return getArguments().get(i);
-    }
-
-    public ExplicitConstructorInvocationStmt setArgument(int i, Expression argument) {
-        getArguments().set(i, argument);
-        return this;
-    }
-
-    public ExplicitConstructorInvocationStmt addArgument(Expression argument) {
-        getArguments().add(argument);
-        return this;
-    }
-
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
     public Optional<Expression> getExpression() {
         return Optional.ofNullable(expression);
@@ -287,7 +274,20 @@
         action.accept(this);
     }
 
-    public ResolvedConstructorDeclaration resolveInvokedConstructor() {
+    /**
+     * Attempts to resolve the declaration corresponding to the invoked constructor. If successful, a
+     * {@link ResolvedConstructorDeclaration} representing the declaration of the constructor invoked by this
+     * {@code ExplicitConstructorInvocationStmt} is returned. Otherwise, an {@link UnsolvedSymbolException} is thrown.
+     *
+     * @return a {@link ResolvedConstructorDeclaration} representing the declaration of the invoked constructor.
+     * @throws UnsolvedSymbolException if the declaration corresponding to the explicit constructor invocation statement
+     *                                 could not be resolved.
+     * @see NameExpr#resolve()
+     * @see FieldAccessExpr#resolve()
+     * @see MethodCallExpr#resolve()
+     * @see ObjectCreationExpr#resolve()
+     */
+    public ResolvedConstructorDeclaration resolve() {
         return getSymbolResolver().resolveDeclaration(this, ResolvedConstructorDeclaration.class);
     }
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExpressionStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExpressionStmt.java
index 483c45d..673b082 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExpressionStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ExpressionStmt.java
@@ -32,17 +32,17 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ExpressionStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Used to wrap an expression so that it can take the place of a statement.
  *
  * @author Julio Vilmar Gesser
  */
-public final class ExpressionStmt extends Statement implements NodeWithExpression<ExpressionStmt> {
+public class ExpressionStmt extends Statement implements NodeWithExpression<ExpressionStmt> {
 
     private Expression expression;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForEachStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForEachStmt.java
new file mode 100644
index 0000000..e843418
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForEachStmt.java
@@ -0,0 +1,243 @@
+/*
+ * 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.stmt;
+
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Generated;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.nodeTypes.NodeWithBody;
+import com.github.javaparser.ast.observer.ObservableProperty;
+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.ForEachStmtMetaModel;
+import com.github.javaparser.metamodel.JavaParserMetaModel;
+import java.util.Optional;
+import java.util.function.Consumer;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+
+/**
+ * A for-each statement.
+ * <br/><code>for(Object o: objects) { ... }</code>
+ * It was introduced in Java 5.
+ *
+ * @author Julio Vilmar Gesser
+ */
+public class ForEachStmt extends Statement implements NodeWithBody<ForEachStmt> {
+
+    private VariableDeclarationExpr variable;
+
+    private Expression iterable;
+
+    private Statement body;
+
+    public ForEachStmt() {
+        this(null, new VariableDeclarationExpr(), new NameExpr(), new ReturnStmt());
+    }
+
+    @AllFieldsConstructor
+    public ForEachStmt(final VariableDeclarationExpr variable, final Expression iterable, final Statement body) {
+        this(null, variable, iterable, body);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public ForEachStmt(TokenRange tokenRange, VariableDeclarationExpr variable, Expression iterable, Statement body) {
+        super(tokenRange);
+        setVariable(variable);
+        setIterable(iterable);
+        setBody(body);
+        customInitialization();
+    }
+
+    public ForEachStmt(VariableDeclarationExpr variable, String iterable, BlockStmt body) {
+        this(null, variable, new NameExpr(iterable), body);
+    }
+
+    @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);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Statement getBody() {
+        return body;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Expression getIterable() {
+        return iterable;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public VariableDeclarationExpr getVariable() {
+        return variable;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ForEachStmt setBody(final Statement body) {
+        assertNotNull(body);
+        if (body == this.body) {
+            return (ForEachStmt) this;
+        }
+        notifyPropertyChange(ObservableProperty.BODY, this.body, body);
+        if (this.body != null)
+            this.body.setParentNode(null);
+        this.body = body;
+        setAsParentNodeOf(body);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ForEachStmt setIterable(final Expression iterable) {
+        assertNotNull(iterable);
+        if (iterable == this.iterable) {
+            return (ForEachStmt) this;
+        }
+        notifyPropertyChange(ObservableProperty.ITERABLE, this.iterable, iterable);
+        if (this.iterable != null)
+            this.iterable.setParentNode(null);
+        this.iterable = iterable;
+        setAsParentNodeOf(iterable);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public ForEachStmt setVariable(final VariableDeclarationExpr variable) {
+        assertNotNull(variable);
+        if (variable == this.variable) {
+            return (ForEachStmt) this;
+        }
+        notifyPropertyChange(ObservableProperty.VARIABLE, this.variable, variable);
+        if (this.variable != null)
+            this.variable.setParentNode(null);
+        this.variable = variable;
+        setAsParentNodeOf(variable);
+        return this;
+    }
+
+    /**
+     * Convenience method that directly returns this foreach statement's single variable declarator.
+     * Note that any foreach statement's variable declaration expression (as returned by {@link #getVariable()}) always
+     * has exactly one variable declarator.
+     * <p>
+     * Calling this method on a foreach statement {@code forEachStmt} is equivalent to calling
+     * {@code forEachStmt.getVariable().getVariable(0)}.
+     *
+     * @return this foreach statement's single variable declarator.
+     */
+    public VariableDeclarator getVariableDeclarator() {
+        return getVariable().getVariable(0);
+    }
+
+    /**
+     * Convenience method that decides whether this foreach statement's variable is {@code final}.
+     * Note that any foreach statement's variable declaration expression (as returned by {@link #getVariable()}) always
+     * has either no modifiers, or a single {@code final} modifier.
+     * <p>
+     * Calling this method on a foreach statement {@code forEachStmt} is equivalent to calling
+     * {@code forEachStmt.getVariable().getModifiers().isNonEmpty() &&
+     * forEachStmt.getVariable().getModifiers().get(0).getKeyword() == Modifier.Keyword.FINAL}.
+     *
+     * @return {@code true} if this foreach statement's variable is {@code final}, and {@code false} otherwise.
+     */
+    public boolean hasFinalVariable() {
+        return getVariable().getModifiers().isNonEmpty() && getVariable().getModifiers().get(0).getKeyword() == Modifier.Keyword.FINAL;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        return super.remove(node);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public ForEachStmt clone() {
+        return (ForEachStmt) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        if (node == body) {
+            setBody((Statement) replacementNode);
+            return true;
+        }
+        if (node == iterable) {
+            setIterable((Expression) replacementNode);
+            return true;
+        }
+        if (node == variable) {
+            setVariable((VariableDeclarationExpr) replacementNode);
+            return true;
+        }
+        return super.replace(node, replacementNode);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isForEachStmt() {
+        return true;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ForEachStmt asForEachStmt() {
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ForEachStmt> toForEachStmt() {
+        return Optional.of(this);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifForEachStmt(Consumer<ForEachStmt> action) {
+        action.accept(this);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public ForEachStmtMetaModel getMetaModel() {
+        return JavaParserMetaModel.forEachStmtMetaModel;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForStmt.java
index d288991..d27ac78 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForStmt.java
@@ -34,10 +34,10 @@
 import com.github.javaparser.metamodel.ForStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.OptionalProperty;
-import javax.annotation.Generated;
 import java.util.Optional;
 import java.util.function.Consumer;
 import static com.github.javaparser.utils.Utils.assertNotNull;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <h1>The classic for statement</h1>
@@ -66,7 +66,7 @@
  * @author Julio Vilmar Gesser
  * @see com.github.javaparser.ast.expr.VariableDeclarationExpr
  */
-public final class ForStmt extends Statement implements NodeWithBody<ForStmt> {
+public class ForStmt extends Statement implements NodeWithBody<ForStmt> {
 
     private NodeList<Expression> initialization;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForeachStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForeachStmt.java
deleted file mode 100644
index 7a04e5b..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ForeachStmt.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.stmt;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.nodeTypes.NodeWithBody;
-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.ForeachStmtMetaModel;
-import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-import java.util.Optional;
-
-/**
- * A for-each statement.
- * <br/><code>for(Object o: objects) { ... }</code>
- *
- * @author Julio Vilmar Gesser
- */
-public final class ForeachStmt extends Statement implements NodeWithBody<ForeachStmt> {
-
-    private VariableDeclarationExpr variable;
-
-    private Expression iterable;
-
-    private Statement body;
-
-    public ForeachStmt() {
-        this(null, new VariableDeclarationExpr(), new NameExpr(), new ReturnStmt());
-    }
-
-    @AllFieldsConstructor
-    public ForeachStmt(final VariableDeclarationExpr variable, final Expression iterable, final Statement body) {
-        this(null, variable, iterable, body);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public ForeachStmt(TokenRange tokenRange, VariableDeclarationExpr variable, Expression iterable, Statement body) {
-        super(tokenRange);
-        setVariable(variable);
-        setIterable(iterable);
-        setBody(body);
-        customInitialization();
-    }
-
-    public ForeachStmt(VariableDeclarationExpr variable, String iterable, BlockStmt body) {
-        this(null, variable, new NameExpr(iterable), body);
-    }
-
-    @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);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Statement getBody() {
-        return body;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Expression getIterable() {
-        return iterable;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public VariableDeclarationExpr getVariable() {
-        return variable;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ForeachStmt setBody(final Statement body) {
-        assertNotNull(body);
-        if (body == this.body) {
-            return (ForeachStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.BODY, this.body, body);
-        if (this.body != null)
-            this.body.setParentNode(null);
-        this.body = body;
-        setAsParentNodeOf(body);
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ForeachStmt setIterable(final Expression iterable) {
-        assertNotNull(iterable);
-        if (iterable == this.iterable) {
-            return (ForeachStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.ITERABLE, this.iterable, iterable);
-        if (this.iterable != null)
-            this.iterable.setParentNode(null);
-        this.iterable = iterable;
-        setAsParentNodeOf(iterable);
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public ForeachStmt setVariable(final VariableDeclarationExpr variable) {
-        assertNotNull(variable);
-        if (variable == this.variable) {
-            return (ForeachStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.VARIABLE, this.variable, variable);
-        if (this.variable != null)
-            this.variable.setParentNode(null);
-        this.variable = variable;
-        setAsParentNodeOf(variable);
-        return this;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        return super.remove(node);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public ForeachStmt clone() {
-        return (ForeachStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public ForeachStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.foreachStmtMetaModel;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        if (node == body) {
-            setBody((Statement) replacementNode);
-            return true;
-        }
-        if (node == iterable) {
-            setIterable((Expression) replacementNode);
-            return true;
-        }
-        if (node == variable) {
-            setVariable((VariableDeclarationExpr) replacementNode);
-            return true;
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isForeachStmt() {
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ForeachStmt asForeachStmt() {
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifForeachStmt(Consumer<ForeachStmt> action) {
-        action.accept(this);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ForeachStmt> toForeachStmt() {
-        return Optional.of(this);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/IfStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/IfStmt.java
index f873ff8..05f38b0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/IfStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/IfStmt.java
@@ -34,10 +34,10 @@
 import com.github.javaparser.metamodel.DerivedProperty;
 import com.github.javaparser.metamodel.IfStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An if-then-else statement. The else is optional.
@@ -46,7 +46,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class IfStmt extends Statement implements NodeWithCondition<IfStmt> {
+public class IfStmt extends Statement implements NodeWithCondition<IfStmt> {
 
     private Expression condition;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LabeledStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LabeledStmt.java
index 7906d0c..a580109 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LabeledStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LabeledStmt.java
@@ -30,17 +30,17 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.LabeledStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A statement that is labeled, like <code>label123: println("continuing");</code>
  *
  * @author Julio Vilmar Gesser
  */
-public final class LabeledStmt extends Statement {
+public class LabeledStmt extends Statement {
 
     private SimpleName label;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LocalClassDeclarationStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LocalClassDeclarationStmt.java
index f78eebc..32d531b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LocalClassDeclarationStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/LocalClassDeclarationStmt.java
@@ -30,10 +30,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.LocalClassDeclarationStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <h1>A class declaration inside a method.</h1>
@@ -46,7 +46,7 @@
  * @see ClassOrInterfaceDeclaration
  * @author Julio Vilmar Gesser
  */
-public final class LocalClassDeclarationStmt extends Statement {
+public class LocalClassDeclarationStmt extends Statement {
 
     private ClassOrInterfaceDeclaration classDeclaration;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ReturnStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ReturnStmt.java
index c9bdb45..fbec826 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ReturnStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ReturnStmt.java
@@ -32,16 +32,16 @@
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.metamodel.ReturnStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The return statement, with an optional expression to return.
  * <br/><code>return 5 * 5;</code>
  * @author Julio Vilmar Gesser
  */
-public final class ReturnStmt extends Statement {
+public class ReturnStmt extends Statement {
 
     @OptionalProperty
     private Expression expression;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/Statement.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/Statement.java
index 75100e8..58d5af4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/Statement.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/Statement.java
@@ -25,8 +25,8 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.StatementMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import java.util.Optional;
@@ -171,16 +171,6 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isForeachStmt() {
-        return false;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public ForeachStmt asForeachStmt() {
-        throw new IllegalStateException(f("%s is not an ForeachStmt", this));
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public boolean isIfStmt() {
         return false;
     }
@@ -221,16 +211,6 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isSwitchEntryStmt() {
-        return false;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public SwitchEntryStmt asSwitchEntryStmt() {
-        throw new IllegalStateException(f("%s is not an SwitchEntryStmt", this));
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public boolean isSwitchStmt() {
         return false;
     }
@@ -327,10 +307,6 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifForeachStmt(Consumer<ForeachStmt> action) {
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public void ifIfStmt(Consumer<IfStmt> action) {
     }
 
@@ -347,10 +323,6 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifSwitchEntryStmt(Consumer<SwitchEntryStmt> action) {
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public void ifSwitchStmt(Consumer<SwitchStmt> action) {
     }
 
@@ -420,11 +392,6 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<ForeachStmt> toForeachStmt() {
-        return Optional.empty();
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public Optional<IfStmt> toIfStmt() {
         return Optional.empty();
     }
@@ -445,11 +412,6 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<SwitchEntryStmt> toSwitchEntryStmt() {
-        return Optional.empty();
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
     public Optional<SwitchStmt> toSwitchStmt() {
         return Optional.empty();
     }
@@ -478,4 +440,23 @@
     public Optional<WhileStmt> toWhileStmt() {
         return Optional.empty();
     }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public boolean isForEachStmt() {
+        return false;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public ForEachStmt asForEachStmt() {
+        throw new IllegalStateException(f("%s is not an ForEachStmt", this));
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public Optional<ForEachStmt> toForEachStmt() {
+        return Optional.empty();
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
+    public void ifForEachStmt(Consumer<ForEachStmt> action) {
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchEntry.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchEntry.java
new file mode 100644
index 0000000..c6cad24
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchEntry.java
@@ -0,0 +1,238 @@
+/*
+ * 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.stmt;
+
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Generated;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.nodeTypes.NodeWithStatements;
+import com.github.javaparser.ast.observer.ObservableProperty;
+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.SwitchEntryMetaModel;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+
+/**
+ * <h1>One case in a switch statement</h1>
+ * The main Javadoc is in {@link SwitchStmt}
+ * <h2>Java 1.0-11</h2>
+ * <pre>
+ * switch (i) {
+ *   case 1:
+ *   case 2:
+ *     System.out.println(444);
+ *     break;
+ *   default:
+ *     System.out.println(0);
+ * }
+ * </pre>
+ * This contains three SwitchEntrys.
+ * <br/>The first one has label 1 and no statements.
+ * <br/>The second has label 2 and two statements (the println and the break).
+ * <br/>The third, the default, has no label and one statement.
+ * <br/>All of them are of type STATEMENT_GROUP.
+ * <h2>Java 12-</h2>
+ * <pre>
+ *     case 1 -> 15*15;
+ *     case 2 -> { a++; b++; }
+ *     case 3 -> throw new Exception();
+ * </pre>
+ * These are three new variants.
+ * <br/>The first one is of type EXPRESSION and stores its {@link Expression} in an {@link ExpressionStmt}
+ * which is stored as the first and only statement in statements.
+ * <br/>The second one is of type BLOCK and stores its {@link BlockStmt} as the first and only statement in statements.
+ * <br/>The third one is of type THROWS_STATEMENT and stores its {@link ThrowStmt} as the first and only statement in statements.
+ * <pre>
+ *     case MONDAY, FRIDAY, SUNDAY -> 6;
+ * </pre>
+ * Multiple case labels are now allowed.
+ * <pre>
+ *     case 16*16, 10+10 -> 6;
+ * </pre>
+ * Many kinds of expressions are now allowed.
+ *
+ * @author Julio Vilmar Gesser
+ * @see SwitchStmt
+ * @see com.github.javaparser.ast.expr.SwitchExpr
+ */
+public class SwitchEntry extends Node implements NodeWithStatements<SwitchEntry> {
+
+    public enum Type {
+
+        STATEMENT_GROUP, EXPRESSION, BLOCK, THROWS_STATEMENT
+    }
+
+    private NodeList<Expression> labels;
+
+    private NodeList<Statement> statements;
+
+    private Type type;
+
+    public SwitchEntry() {
+        this(null, new NodeList<Expression>(), Type.STATEMENT_GROUP, new NodeList<>());
+    }
+
+    @AllFieldsConstructor
+    public SwitchEntry(final NodeList<Expression> labels, final Type type, final NodeList<Statement> statements) {
+        this(null, labels, type, statements);
+    }
+
+    /**
+     * This constructor is used by the parser and is considered private.
+     */
+    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
+    public SwitchEntry(TokenRange tokenRange, NodeList<Expression> labels, Type type, NodeList<Statement> statements) {
+        super(tokenRange);
+        setLabels(labels);
+        setType(type);
+        setStatements(statements);
+        customInitialization();
+    }
+
+    @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);
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public NodeList<Expression> getLabels() {
+        return labels;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public NodeList<Statement> getStatements() {
+        return statements;
+    }
+
+    /**
+     * Sets the label
+     *
+     * @param labels the label, can be null
+     * @return this, the SwitchEntry
+     */
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public SwitchEntry setLabels(final NodeList<Expression> labels) {
+        assertNotNull(labels);
+        if (labels == this.labels) {
+            return (SwitchEntry) this;
+        }
+        notifyPropertyChange(ObservableProperty.LABELS, this.labels, labels);
+        if (this.labels != null)
+            this.labels.setParentNode(null);
+        this.labels = labels;
+        setAsParentNodeOf(labels);
+        return this;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public SwitchEntry setStatements(final NodeList<Statement> statements) {
+        assertNotNull(statements);
+        if (statements == this.statements) {
+            return (SwitchEntry) this;
+        }
+        notifyPropertyChange(ObservableProperty.STATEMENTS, this.statements, statements);
+        if (this.statements != null)
+            this.statements.setParentNode(null);
+        this.statements = statements;
+        setAsParentNodeOf(statements);
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
+    public boolean remove(Node node) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < labels.size(); i++) {
+            if (labels.get(i) == node) {
+                labels.remove(i);
+                return true;
+            }
+        }
+        for (int i = 0; i < statements.size(); i++) {
+            if (statements.get(i) == node) {
+                statements.remove(i);
+                return true;
+            }
+        }
+        return super.remove(node);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
+    public SwitchEntry clone() {
+        return (SwitchEntry) accept(new CloneVisitor(), null);
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
+    public SwitchEntryMetaModel getMetaModel() {
+        return JavaParserMetaModel.switchEntryMetaModel;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public Type getType() {
+        return type;
+    }
+
+    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
+    public SwitchEntry setType(final Type type) {
+        assertNotNull(type);
+        if (type == this.type) {
+            return (SwitchEntry) this;
+        }
+        notifyPropertyChange(ObservableProperty.TYPE, this.type, type);
+        this.type = type;
+        return this;
+    }
+
+    @Override
+    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
+    public boolean replace(Node node, Node replacementNode) {
+        if (node == null)
+            return false;
+        for (int i = 0; i < labels.size(); i++) {
+            if (labels.get(i) == node) {
+                labels.set(i, (Expression) replacementNode);
+                return true;
+            }
+        }
+        for (int i = 0; i < statements.size(); i++) {
+            if (statements.get(i) == node) {
+                statements.set(i, (Statement) replacementNode);
+                return true;
+            }
+        }
+        return super.replace(node, replacementNode);
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchEntryStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchEntryStmt.java
deleted file mode 100644
index afa8fce..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchEntryStmt.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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.stmt;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.nodeTypes.NodeWithStatements;
-import com.github.javaparser.ast.observer.ObservableProperty;
-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;
-import com.github.javaparser.ast.visitor.CloneVisitor;
-import com.github.javaparser.metamodel.OptionalProperty;
-import com.github.javaparser.metamodel.SwitchEntryStmtMetaModel;
-import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
-import com.github.javaparser.TokenRange;
-import java.util.function.Consumer;
-
-/**
- * One case in a switch statement.
- * <br/><pre>
- * switch (i) {
- * case 1:
- * case 2:
- * System.out.println(444);
- * break;
- * default:
- * System.out.println(0);
- * }
- * </pre>
- * This contains three SwitchEntryStmts.
- * <br/>The first one has label 1 and no statements.
- * <br/>The second has label 2 and two statements (the println and the break).
- * <br/>The third, the default, has no label and one statement.
- *
- * @author Julio Vilmar Gesser
- * @see SwitchStmt
- */
-public final class SwitchEntryStmt extends Statement implements NodeWithStatements<SwitchEntryStmt> {
-
-    @OptionalProperty
-    private Expression label;
-
-    private NodeList<Statement> statements;
-
-    public SwitchEntryStmt() {
-        this(null, null, new NodeList<>());
-    }
-
-    @AllFieldsConstructor
-    public SwitchEntryStmt(final Expression label, final NodeList<Statement> statements) {
-        this(null, label, statements);
-    }
-
-    /**
-     * This constructor is used by the parser and is considered private.
-     */
-    @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public SwitchEntryStmt(TokenRange tokenRange, Expression label, NodeList<Statement> statements) {
-        super(tokenRange);
-        setLabel(label);
-        setStatements(statements);
-        customInitialization();
-    }
-
-    @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);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public Optional<Expression> getLabel() {
-        return Optional.ofNullable(label);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public NodeList<Statement> getStatements() {
-        return statements;
-    }
-
-    /**
-     * Sets the label
-     *
-     * @param label the label, can be null
-     * @return this, the SwitchEntryStmt
-     */
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public SwitchEntryStmt setLabel(final Expression label) {
-        if (label == this.label) {
-            return (SwitchEntryStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.LABEL, this.label, label);
-        if (this.label != null)
-            this.label.setParentNode(null);
-        this.label = label;
-        setAsParentNodeOf(label);
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public SwitchEntryStmt setStatements(final NodeList<Statement> statements) {
-        assertNotNull(statements);
-        if (statements == this.statements) {
-            return (SwitchEntryStmt) this;
-        }
-        notifyPropertyChange(ObservableProperty.STATEMENTS, this.statements, statements);
-        if (this.statements != null)
-            this.statements.setParentNode(null);
-        this.statements = statements;
-        setAsParentNodeOf(statements);
-        return this;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public boolean remove(Node node) {
-        if (node == null)
-            return false;
-        if (label != null) {
-            if (node == label) {
-                removeLabel();
-                return true;
-            }
-        }
-        for (int i = 0; i < statements.size(); i++) {
-            if (statements.get(i) == node) {
-                statements.remove(i);
-                return true;
-            }
-        }
-        return super.remove(node);
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
-    public SwitchEntryStmt removeLabel() {
-        return setLabel((Expression) null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
-    public SwitchEntryStmt clone() {
-        return (SwitchEntryStmt) accept(new CloneVisitor(), null);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
-    public SwitchEntryStmtMetaModel getMetaModel() {
-        return JavaParserMetaModel.switchEntryStmtMetaModel;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
-    public boolean replace(Node node, Node replacementNode) {
-        if (node == null)
-            return false;
-        if (label != null) {
-            if (node == label) {
-                setLabel((Expression) replacementNode);
-                return true;
-            }
-        }
-        for (int i = 0; i < statements.size(); i++) {
-            if (statements.get(i) == node) {
-                statements.set(i, (Statement) replacementNode);
-                return true;
-            }
-        }
-        return super.replace(node, replacementNode);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public boolean isSwitchEntryStmt() {
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public SwitchEntryStmt asSwitchEntryStmt() {
-        return this;
-    }
-
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public void ifSwitchEntryStmt(Consumer<SwitchEntryStmt> action) {
-        action.accept(this);
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
-    public Optional<SwitchEntryStmt> toSwitchEntryStmt() {
-        return Optional.of(this);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchStmt.java
index 36e88b2..af1d356 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SwitchStmt.java
@@ -24,41 +24,64 @@
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.nodeTypes.SwitchNode;
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 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.SwitchStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
- * A switch statement.
+ * <h1>The switch statement</h1>
+ *
+ * <h2>Java 1.0-1.4</h2>
+ * The basic C-like switch statement.
+ * It can switch only on integers.
+ * <br/><code>switch(x) { case 5: case 6: a=100; break; case 9: a=33; break; default: throw new IllegalStateException(); };</code>
  * <br/>In <code>switch(a) { ... }</code> the selector is "a",
  * and the contents of the { ... } are the entries.
  *
+ * <h2>Java 5-6</h2>
+ * Switching can now also be done on enum constants.
+ *
+ * <h2>Java 7-11</h2>
+ * Switching can now also be done on strings.
+ *
+ * <h2>Java 12-</h2>
+ * In preparation for pattern matching, lots of changes are made:
+ * <ul>
+ * <li>multiple labels per case
+ * <li>a -> syntax that does not fall through.
+ * <li>break can take any expression (usable in the {@link com.github.javaparser.ast.expr.SwitchExpr})
+ * <li>switch can be used as an expression (it becomes a {@link com.github.javaparser.ast.expr.SwitchExpr})
+ * </ul>
+ * <code>switch(x) { case BANANA,PEAR: b=10; break; default: b=5; };</code>
+ * <br/><code>switch(x) { case 5,6 -> println("uhuh"); default -> println("nope"); };</code>
+ *
  * @author Julio Vilmar Gesser
- * @see SwitchEntryStmt
+ * @see SwitchEntry
+ * @see com.github.javaparser.ast.expr.SwitchExpr
+ * @see SwitchNode
  */
-public final class SwitchStmt extends Statement {
+public class SwitchStmt extends Statement implements SwitchNode {
 
     private Expression selector;
 
-    private NodeList<SwitchEntryStmt> entries;
+    private NodeList<SwitchEntry> entries;
 
     public SwitchStmt() {
         this(null, new NameExpr(), new NodeList<>());
     }
 
     @AllFieldsConstructor
-    public SwitchStmt(final Expression selector, final NodeList<SwitchEntryStmt> entries) {
+    public SwitchStmt(final Expression selector, final NodeList<SwitchEntry> entries) {
         this(null, selector, entries);
     }
 
@@ -66,7 +89,7 @@
      * This constructor is used by the parser and is considered private.
      */
     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
-    public SwitchStmt(TokenRange tokenRange, Expression selector, NodeList<SwitchEntryStmt> entries) {
+    public SwitchStmt(TokenRange tokenRange, Expression selector, NodeList<SwitchEntry> entries) {
         super(tokenRange);
         setSelector(selector);
         setEntries(entries);
@@ -86,11 +109,11 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public NodeList<SwitchEntryStmt> getEntries() {
+    public NodeList<SwitchEntry> getEntries() {
         return entries;
     }
 
-    public SwitchEntryStmt getEntry(int i) {
+    public SwitchEntry getEntry(int i) {
         return getEntries().get(i);
     }
 
@@ -100,7 +123,7 @@
     }
 
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
-    public SwitchStmt setEntries(final NodeList<SwitchEntryStmt> entries) {
+    public SwitchStmt setEntries(final NodeList<SwitchEntry> entries) {
         assertNotNull(entries);
         if (entries == this.entries) {
             return (SwitchStmt) this;
@@ -113,24 +136,6 @@
         return this;
     }
 
-    /**
-     * @deprecated use a method on getEntries instead
-     */
-    @Deprecated
-    public SwitchStmt setEntry(int i, SwitchEntryStmt entry) {
-        getEntries().set(i, entry);
-        return this;
-    }
-
-    /**
-     * @deprecated use a method on getEntries instead
-     */
-    @Deprecated
-    public SwitchStmt addEntry(SwitchEntryStmt entry) {
-        getEntries().add(entry);
-        return this;
-    }
-
     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
     public SwitchStmt setSelector(final Expression selector) {
         assertNotNull(selector);
@@ -178,7 +183,7 @@
             return false;
         for (int i = 0; i < entries.size(); i++) {
             if (entries.get(i) == node) {
-                entries.set(i, (SwitchEntryStmt) replacementNode);
+                entries.set(i, (SwitchEntry) replacementNode);
                 return true;
             }
         }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SynchronizedStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SynchronizedStmt.java
index 376d525..127cc16 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SynchronizedStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/SynchronizedStmt.java
@@ -33,10 +33,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.SynchronizedStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Usage of the synchronized keyword.
@@ -44,7 +44,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class SynchronizedStmt extends Statement implements NodeWithBlockStmt<SynchronizedStmt>, NodeWithExpression<SynchronizedStmt> {
+public class SynchronizedStmt extends Statement implements NodeWithBlockStmt<SynchronizedStmt>, NodeWithExpression<SynchronizedStmt> {
 
     private Expression expression;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ThrowStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ThrowStmt.java
index 736b835..22bf016 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ThrowStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/ThrowStmt.java
@@ -32,10 +32,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.ThrowStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Usage of the throw statement.
@@ -43,7 +43,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ThrowStmt extends Statement implements NodeWithExpression<ThrowStmt> {
+public class ThrowStmt extends Statement implements NodeWithExpression<ThrowStmt> {
 
     private Expression expression;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/TryStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/TryStmt.java
index 6e4a81a..dcb1048 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/TryStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/TryStmt.java
@@ -32,12 +32,10 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.metamodel.TryStmtMetaModel;
-import javax.annotation.Generated;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Optional;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <h1>The try statement</h1>
@@ -94,7 +92,7 @@
  * @see com.github.javaparser.ast.expr.FieldAccessExpr
  * @see com.github.javaparser.ast.expr.NameExpr
  */
-public final class TryStmt extends Statement {
+public class TryStmt extends Statement {
 
     private NodeList<Expression> resources;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/UnparsableStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/UnparsableStmt.java
index 2a7fc01..ddd92b4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/UnparsableStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/UnparsableStmt.java
@@ -5,19 +5,19 @@
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.ast.Node;
-import javax.annotation.Generated;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.UnparsableStmtMetaModel;
 import static com.github.javaparser.ast.Node.Parsedness.*;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A statement that had parse errors.
  * Nothing is known about it except the tokens it covers.
  */
-public final class UnparsableStmt extends Statement {
+public class UnparsableStmt extends Statement {
 
     @AllFieldsConstructor
     public UnparsableStmt() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/WhileStmt.java b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/WhileStmt.java
index 5fb1f99..9edadb2 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/WhileStmt.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/stmt/WhileStmt.java
@@ -33,10 +33,10 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.WhileStmtMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A while statement.
@@ -44,7 +44,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class WhileStmt extends Statement implements NodeWithBody<WhileStmt>, NodeWithCondition<WhileStmt> {
+public class WhileStmt extends Statement implements NodeWithBody<WhileStmt>, NodeWithCondition<WhileStmt> {
 
     private Expression condition;
 
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 76dba1f..6d8c76f 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
@@ -34,19 +34,19 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.resolution.types.ResolvedArrayType;
 import com.github.javaparser.utils.Pair;
-import javax.annotation.Generated;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import static com.github.javaparser.ast.NodeList.nodeList;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * To indicate that a type is an array, it gets wrapped in an ArrayType for every array level it has.
  * So, int[][] becomes ArrayType(ArrayType(int)).
  */
-public final class ArrayType extends ReferenceType implements NodeWithAnnotations<ArrayType> {
+public class ArrayType extends ReferenceType implements NodeWithAnnotations<ArrayType> {
 
     @Override
     public ResolvedArrayType resolve() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java
index f3b6846..8bc23f1 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ClassOrInterfaceType.java
@@ -34,16 +34,14 @@
 import com.github.javaparser.ast.visitor.VoidVisitor;
 import com.github.javaparser.metamodel.ClassOrInterfaceTypeMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Optional;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import static java.util.stream.Collectors.joining;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import java.util.function.Consumer;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A class or an interface type. <br/><code>Object</code> <br/><code>HashMap&lt;String, String></code>
@@ -57,7 +55,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class ClassOrInterfaceType extends ReferenceType implements NodeWithSimpleName<ClassOrInterfaceType>, NodeWithAnnotations<ClassOrInterfaceType>, NodeWithTypeArguments<ClassOrInterfaceType> {
+public class ClassOrInterfaceType extends ReferenceType implements NodeWithSimpleName<ClassOrInterfaceType>, NodeWithAnnotations<ClassOrInterfaceType>, NodeWithTypeArguments<ClassOrInterfaceType> {
 
     @OptionalProperty
     private ClassOrInterfaceType scope;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java
index 6b1056b..aefa8b6 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/IntersectionType.java
@@ -32,16 +32,13 @@
 import com.github.javaparser.metamodel.IntersectionTypeMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.NonEmptyProperty;
-import java.util.Arrays;
-import java.util.List;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import static java.util.stream.Collectors.joining;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.types.ResolvedIntersectionType;
-import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * Represents a set of types. A given value of this type has to be assignable to at all of the element types.
@@ -55,7 +52,7 @@
  *
  * @since 3.0.0
  */
-public final class IntersectionType extends Type implements NodeWithAnnotations<IntersectionType> {
+public class IntersectionType extends Type implements NodeWithAnnotations<IntersectionType> {
 
     @NonEmptyProperty
     private NodeList<ReferenceType> elements;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java
index e359b7f..7837087 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/PrimitiveType.java
@@ -27,21 +27,18 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
+import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
 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.PrimitiveTypeMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
-import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A primitive type.
@@ -51,7 +48,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class PrimitiveType extends Type implements NodeWithAnnotations<PrimitiveType> {
+public class PrimitiveType extends Type implements NodeWithAnnotations<PrimitiveType> {
 
     public static PrimitiveType booleanType() {
         return new PrimitiveType(Primitive.BOOLEAN);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java
index f39ee0e..921300a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/ReferenceType.java
@@ -28,7 +28,7 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.ReferenceTypeMetaModel;
-import javax.annotation.Generated;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 import java.util.Optional;
 
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 acaf5a9..38212c3 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
@@ -21,7 +21,6 @@
 package com.github.javaparser.ast.type;
 
 import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.DataKey;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.expr.AnnotationExpr;
@@ -30,13 +29,11 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.TypeMetaModel;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.Resolvable;
-import com.github.javaparser.resolution.SymbolResolver;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
-import java.util.function.Supplier;
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 import java.util.Optional;
 
@@ -45,7 +42,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public abstract class Type extends Node implements Resolvable<Object> {
+public abstract class Type extends Node implements Resolvable<ResolvedType> {
 
     private NodeList<AnnotationExpr> annotations;
 
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 c3f8ced..d8a022d 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
@@ -36,12 +36,11 @@
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.TypeParameterMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
-import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.types.ResolvedTypeVariable;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * A type parameter.
@@ -55,7 +54,7 @@
  * @author Julio Vilmar Gesser
  * @see com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters
  */
-public final class TypeParameter extends ReferenceType implements NodeWithSimpleName<TypeParameter>, NodeWithAnnotations<TypeParameter> {
+public class TypeParameter extends ReferenceType implements NodeWithSimpleName<TypeParameter>, NodeWithAnnotations<TypeParameter> {
 
     private SimpleName name;
 
@@ -73,15 +72,6 @@
         this(null, new SimpleName(name), typeBound, new NodeList<>());
     }
 
-    /**
-     * @deprecated range shouldn't be in utility constructors.
-     */
-    @Deprecated
-    public TypeParameter(Range range, final SimpleName name, final NodeList<ClassOrInterfaceType> typeBound) {
-        this(null, name, typeBound, new NodeList<>());
-        setRange(range);
-    }
-
     @AllFieldsConstructor
     public TypeParameter(SimpleName name, NodeList<ClassOrInterfaceType> typeBound, NodeList<AnnotationExpr> annotations) {
         this(null, name, typeBound, annotations);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java
index 5fa78f1..a8a9306 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnionType.java
@@ -27,8 +27,6 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 import static com.github.javaparser.utils.Utils.assertNotNull;
 import static java.util.stream.Collectors.joining;
 import com.github.javaparser.ast.Node;
@@ -36,12 +34,11 @@
 import com.github.javaparser.metamodel.NonEmptyProperty;
 import com.github.javaparser.metamodel.UnionTypeMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
-import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedUnionType;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * <h1>The union type</h1>
@@ -60,7 +57,7 @@
  *
  * The types that make up the union type are its "elements"
  */
-public final class UnionType extends Type implements NodeWithAnnotations<UnionType> {
+public class UnionType extends Type implements NodeWithAnnotations<UnionType> {
 
     @NonEmptyProperty
     private NodeList<ReferenceType> elements;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java
index d415214..bf50a29 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/UnknownType.java
@@ -25,19 +25,16 @@
 import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.UnknownTypeMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.resolution.types.ResolvedUnionType;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * An unknown parameter type object. It plays the role of a null object for
@@ -48,7 +45,7 @@
  *
  * @author Didier Villevalois
  */
-public final class UnknownType extends Type {
+public class UnknownType extends Type {
 
     @AllFieldsConstructor
     public UnknownType() {
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
index 3755c2f..f4a669d 100644
--- 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
@@ -25,20 +25,25 @@
 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.ResolvedType;
-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;
+import com.github.javaparser.ast.Generated;
 
-public final class VarType extends Type {
+/**
+ * <h1>A type called "var" waiting for Java to infer it.</h1>
+ * Examples:
+ * <ol>
+ * <li><b>var</b> a = 1;</li>
+ * <li><b>var</b> a = new ArrayList&lt;String>();</li>
+ * </ol>
+ */
+public class VarType extends Type {
 
     @AllFieldsConstructor
     public VarType() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java
index 860a9d6..9842d93 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/VoidType.java
@@ -26,18 +26,15 @@
 import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
 import com.github.javaparser.ast.visitor.GenericVisitor;
 import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.Arrays;
-import java.util.List;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.visitor.CloneVisitor;
 import com.github.javaparser.metamodel.VoidTypeMetaModel;
 import com.github.javaparser.metamodel.JavaParserMetaModel;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
-import com.github.javaparser.resolution.types.ResolvedUnionType;
 import com.github.javaparser.resolution.types.ResolvedVoidType;
 import java.util.function.Consumer;
 import java.util.Optional;
+import com.github.javaparser.ast.Generated;
 
 /**
  * The return type of a {@link com.github.javaparser.ast.body.MethodDeclaration}
@@ -46,7 +43,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class VoidType extends Type implements NodeWithAnnotations<VoidType> {
+public class VoidType extends Type implements NodeWithAnnotations<VoidType> {
 
     @AllFieldsConstructor
     public VoidType() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java b/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java
index e37842e..8613e06 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/type/WildcardType.java
@@ -32,13 +32,10 @@
 import com.github.javaparser.metamodel.JavaParserMetaModel;
 import com.github.javaparser.metamodel.OptionalProperty;
 import com.github.javaparser.metamodel.WildcardTypeMetaModel;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Optional;
-import javax.annotation.Generated;
 import com.github.javaparser.TokenRange;
-import com.github.javaparser.resolution.types.ResolvedUnionType;
 import com.github.javaparser.resolution.types.ResolvedWildcard;
+import com.github.javaparser.ast.Generated;
 import java.util.function.Consumer;
 
 /**
@@ -49,7 +46,7 @@
  *
  * @author Julio Vilmar Gesser
  */
-public final class WildcardType extends Type implements NodeWithAnnotations<WildcardType> {
+public class WildcardType extends Type implements NodeWithAnnotations<WildcardType> {
 
     @OptionalProperty
     private ReferenceType extendedType;
@@ -104,22 +101,6 @@
     }
 
     /**
-     * @deprecated use getExtendedType instead.
-     */
-    @Deprecated
-    public Optional<ReferenceType> getExtendedTypes() {
-        return getExtendedType();
-    }
-
-    /**
-     * @deprecated use getSuperType instead.
-     */
-    @Deprecated
-    public Optional<ReferenceType> getSuperTypes() {
-        return getSuperType();
-    }
-
-    /**
      * Sets the extended type
      *
      * @param extendedType the extends, can be null
@@ -139,18 +120,6 @@
     }
 
     /**
-     * Sets the extended type
-     *
-     * @param extendedType the extends, can be null
-     * @return this, the WildcardType
-     * @deprecated use setExtendedType instead,
-     */
-    @Deprecated
-    public WildcardType setExtendedTypes(final ReferenceType extendedType) {
-        return setExtendedType(extendedType);
-    }
-
-    /**
      * Sets the supertype
      *
      * @param superType the super, can be null
@@ -169,18 +138,6 @@
         return this;
     }
 
-    /**
-     * Sets the supertype
-     *
-     * @param superType the super, can be null
-     * @return this, the WildcardType
-     * @deprecated use setSuperType instead
-     */
-    @Deprecated
-    public WildcardType setSuperTypes(final ReferenceType superType) {
-        return setSuperType(superType);
-    }
-
     @Override
     public WildcardType setAnnotations(NodeList<AnnotationExpr> annotations) {
         return (WildcardType) super.setAnnotations(annotations);
@@ -214,16 +171,6 @@
         return str.toString();
     }
 
-    @Deprecated
-    public WildcardType removeExtendedTypes() {
-        return removeExtendedType();
-    }
-
-    @Deprecated
-    public WildcardType removeSuperTypes() {
-        return removeSuperType();
-    }
-
     @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
     public WildcardType removeExtendedType() {
         return setExtendedType((ReferenceType) null);
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
index c7fda2f..fe94ac6 100644
--- 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
@@ -8,7 +8,7 @@
  */
 public class Java10Validator extends Java9Validator {
 
-    protected final Validator varOnlyOnLocalVariableDefinitionAndFor = new SingleNodeTypeValidator<>(VarType.class, new VarValidator(false));
+    final Validator varOnlyOnLocalVariableDefinitionAndFor = new SingleNodeTypeValidator<>(VarType.class, new VarValidator(false));
 
     public Java10Validator() {
         super();
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java11Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java11Validator.java
index 0eb879a..bf574c0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java11Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java11Validator.java
@@ -7,7 +7,7 @@
  * This validator validates according to Java 11 syntax rules.
  */
 public class Java11Validator extends Java10Validator {
-    protected final Validator varAlsoInLambdaParameters = new SingleNodeTypeValidator<>(VarType.class, new VarValidator(true));
+    final Validator varAlsoInLambdaParameters = new SingleNodeTypeValidator<>(VarType.class, new VarValidator(true));
 
     public Java11Validator() {
         super();
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java12Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java12Validator.java
new file mode 100644
index 0000000..b8efbd9
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java12Validator.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.ast.validator;
+
+/**
+ * This validator validates according to Java 12 syntax rules.
+ */
+public class Java12Validator extends Java11Validator {
+
+    public Java12Validator() {
+        super();
+        remove(noSwitchExpressions);
+        remove(onlyOneLabelInSwitchCase);
+        remove(noValueBreak);
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_0Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_0Validator.java
index 0d1051d..76fff5e 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_0Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_0Validator.java
@@ -2,18 +2,15 @@
 
 import com.github.javaparser.ast.ImportDeclaration;
 import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.expr.AnnotationExpr;
-import com.github.javaparser.ast.expr.ClassExpr;
-import com.github.javaparser.ast.expr.LambdaExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
+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.Parameter;
+import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.modules.ModuleDeclaration;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters;
-import com.github.javaparser.ast.stmt.AssertStmt;
-import com.github.javaparser.ast.stmt.ForeachStmt;
-import com.github.javaparser.ast.stmt.SwitchEntryStmt;
-import com.github.javaparser.ast.stmt.TryStmt;
+import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.UnionType;
 import com.github.javaparser.ast.validator.chunks.CommonValidators;
 import com.github.javaparser.ast.validator.chunks.ModifierValidator;
@@ -24,21 +21,21 @@
  * This validator validates according to Java 1.0 syntax rules.
  */
 public class Java1_0Validator extends Validators {
-    protected final Validator modifiersWithoutStrictfpAndDefaultAndStaticInterfaceMethodsAndPrivateInterfaceMethods
+    final Validator modifiersWithoutStrictfpAndDefaultAndStaticInterfaceMethodsAndPrivateInterfaceMethods
             = new ModifierValidator(false, false, false);
-    protected final Validator noAssertKeyword = new SimpleValidator<>(AssertStmt.class,
+    final Validator noAssertKeyword = new SimpleValidator<>(AssertStmt.class,
             n -> true,
             (n, reporter) -> reporter.report(n, "'assert' keyword is not supported.")
     );
-    protected final Validator noInnerClasses = new SimpleValidator<>(ClassOrInterfaceDeclaration.class,
+    final Validator noInnerClasses = new SimpleValidator<>(ClassOrInterfaceDeclaration.class,
             n -> !n.isTopLevelType(),
             (n, reporter) -> reporter.report(n, "inner classes or interfaces are not supported.")
     );
-    protected final Validator noReflection = new SimpleValidator<>(ClassExpr.class,
+    final Validator noReflection = new SimpleValidator<>(ClassExpr.class,
             n -> true,
             (n, reporter) -> reporter.report(n, "Reflection is not supported.")
     );
-    protected final Validator noGenerics = new TreeVisitorValidator((node, reporter) -> {
+    final Validator noGenerics = new TreeVisitorValidator((node, reporter) -> {
         if (node instanceof NodeWithTypeArguments) {
             if (((NodeWithTypeArguments<? extends Node>) node).getTypeArguments().isPresent()) {
                 reporter.report(node, "Generics are not supported.");
@@ -50,7 +47,7 @@
             }
         }
     });
-    protected final SingleNodeTypeValidator<TryStmt> tryWithoutResources = new SingleNodeTypeValidator<>(TryStmt.class, (n, reporter) -> {
+    final SingleNodeTypeValidator<TryStmt> tryWithoutResources = new SingleNodeTypeValidator<>(TryStmt.class, (n, reporter) -> {
         if (n.getCatchClauses().isEmpty() && !n.getFinallyBlock().isPresent()) {
             reporter.report(n, "Try has no finally and no catch.");
         }
@@ -58,45 +55,53 @@
             reporter.report(n, "Catch with resource is not supported.");
         }
     });
-    protected final Validator noAnnotations = new TreeVisitorValidator((node, reporter) -> {
+    final Validator noAnnotations = new TreeVisitorValidator((node, reporter) -> {
         if (node instanceof AnnotationExpr || node instanceof AnnotationDeclaration) {
             reporter.report(node, "Annotations are not supported.");
         }
     });
-    protected final Validator noEnums = new SimpleValidator<>(EnumDeclaration.class,
+    final Validator noEnums = new SimpleValidator<>(EnumDeclaration.class,
             n -> true,
             (n, reporter) -> reporter.report(n, "Enumerations are not supported.")
     );
-    protected final Validator noVarargs = new SimpleValidator<>(Parameter.class,
+    final Validator noVarargs = new SimpleValidator<>(Parameter.class,
             Parameter::isVarArgs,
             (n, reporter) -> reporter.report(n, "Varargs are not supported.")
     );
-    protected final Validator noForEach = new SimpleValidator<>(ForeachStmt.class,
+    final Validator noForEach = new SimpleValidator<>(ForEachStmt.class,
             n -> true,
             (n, reporter) -> reporter.report(n, "For-each loops are not supported.")
     );
-    protected final Validator noStaticImports = new SimpleValidator<>(ImportDeclaration.class,
+    final Validator noStaticImports = new SimpleValidator<>(ImportDeclaration.class,
             ImportDeclaration::isStatic,
             (n, reporter) -> reporter.report(n, "Static imports are not supported.")
     );
-    protected final Validator noStringsInSwitch = new SimpleValidator<>(SwitchEntryStmt.class,
-            n -> n.getLabel().map(l -> l instanceof StringLiteralExpr).orElse(false),
-            (n, reporter) -> reporter.report(n.getLabel().get(), "Strings in switch statements are not supported.")
+    final Validator onlyOneLabelInSwitchCase = new SimpleValidator<>(SwitchEntry.class,
+            n -> n.getLabels().size() > 1,
+            (n, reporter) -> reporter.report(n.getLabels().getParentNode().get(), "Only one label allowed in a switch-case.")
     );
-    protected final Validator noBinaryIntegerLiterals = new NoBinaryIntegerLiteralsValidator();
-    protected final Validator noUnderscoresInIntegerLiterals = new NoUnderscoresInIntegerLiteralsValidator();
-    protected final Validator noMultiCatch = new SimpleValidator<>(UnionType.class,
+    final Validator noValueBreak = new SimpleValidator<>(BreakStmt.class,
+            n -> n.getValue().map(expression -> !expression.isNameExpr()).orElse(false),
+            (n, reporter) -> reporter.report(n, "Only labels allowed in break statements.")
+    );
+    final Validator noBinaryIntegerLiterals = new NoBinaryIntegerLiteralsValidator();
+    final Validator noUnderscoresInIntegerLiterals = new NoUnderscoresInIntegerLiteralsValidator();
+    final Validator noMultiCatch = new SimpleValidator<>(UnionType.class,
             n -> true,
             (n, reporter) -> reporter.report(n, "Multi-catch is not supported.")
     );
-    protected final Validator noLambdas = new SimpleValidator<>(LambdaExpr.class,
+    final Validator noLambdas = new SimpleValidator<>(LambdaExpr.class,
             n -> true,
             (n, reporter) -> reporter.report(n, "Lambdas are not supported.")
     );
-    protected final Validator noModules = new SimpleValidator<>(ModuleDeclaration.class,
+    final Validator noModules = new SimpleValidator<>(ModuleDeclaration.class,
             n -> true,
             (n, reporter) -> reporter.report(n, "Modules are not supported.")
     );
+    final Validator noSwitchExpressions = new SimpleValidator<>(SwitchExpr.class,
+            n -> true,
+            (n, reporter) -> reporter.report(n, "Switch expressions are not supported.")
+    );
 
     public Java1_0Validator() {
         super(new CommonValidators());
@@ -111,11 +116,13 @@
         add(noVarargs);
         add(noForEach);
         add(noStaticImports);
-        add(noStringsInSwitch);
+        add(noValueBreak);
+        add(onlyOneLabelInSwitchCase);
         add(noBinaryIntegerLiterals);
         add(noUnderscoresInIntegerLiterals);
         add(noMultiCatch);
         add(noLambdas);
         add(noModules);
+        add(noSwitchExpressions);
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_1Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_1Validator.java
index 5279b7f..ed8356d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_1Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_1Validator.java
@@ -7,7 +7,7 @@
  * This validator validates according to Java 1.1 syntax rules.
  */
 public class Java1_1Validator extends Java1_0Validator {
-    protected final Validator innerClasses = new SingleNodeTypeValidator<>(ClassOrInterfaceDeclaration.class,
+    final Validator innerClasses = new SingleNodeTypeValidator<>(ClassOrInterfaceDeclaration.class,
             (n, reporter) -> n.getParentNode().ifPresent(p -> {
                 if (p instanceof LocalClassDeclarationStmt && n.isInterface())
                     reporter.report(n, "There is no such thing as a local interface.");
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_2Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_2Validator.java
index 4ac7565..edf0bcb 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_2Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java1_2Validator.java
@@ -6,8 +6,8 @@
  * This validator validates according to Java 1.2 syntax rules.
  */
 public class Java1_2Validator extends Java1_1Validator {
-    protected final Validator modifiersWithoutDefaultAndStaticInterfaceMethodsAndPrivateInterfaceMethods = new ModifierValidator(true, false, false);
-    protected final Validator strictfpNotAllowed = new ReservedKeywordValidator("strictfp");
+    final Validator modifiersWithoutDefaultAndStaticInterfaceMethodsAndPrivateInterfaceMethods = new ModifierValidator(true, false, false);
+    final Validator strictfpNotAllowed = new ReservedKeywordValidator("strictfp");
     
     public Java1_2Validator() {
         super();
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java5Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java5Validator.java
index d8b1aab..b574130 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java5Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java5Validator.java
@@ -2,7 +2,11 @@
 
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
+import com.github.javaparser.ast.stmt.ForEachStmt;
+import com.github.javaparser.ast.stmt.SwitchEntry;
 import com.github.javaparser.ast.type.PrimitiveType;
 import com.github.javaparser.ast.type.Type;
 
@@ -12,7 +16,7 @@
  * This validator validates according to Java 5 syntax rules.
  */
 public class Java5Validator extends Java1_4Validator {
-    Validator genericsWithoutDiamondOperator = new TreeVisitorValidator((node, reporter) -> {
+    final Validator genericsWithoutDiamondOperator = new TreeVisitorValidator((node, reporter) -> {
         if (node instanceof NodeWithTypeArguments) {
             Optional<NodeList<Type>> typeArguments = ((NodeWithTypeArguments<? extends Node>) node).getTypeArguments();
             if (typeArguments.isPresent() && typeArguments.get().isEmpty()) {
@@ -21,7 +25,7 @@
         }
     });
 
-    protected Validator noPrimitiveGenericArguments = new TreeVisitorValidator((node, reporter) -> {
+    protected final Validator noPrimitiveGenericArguments = new TreeVisitorValidator((node, reporter) -> {
         if (node instanceof NodeWithTypeArguments) {
             Optional<NodeList<Type>> typeArguments = ((NodeWithTypeArguments<? extends Node>) node).getTypeArguments();
             typeArguments.ifPresent(types -> types.forEach(ty -> {
@@ -32,14 +36,26 @@
         }
     });
 
-    protected final Validator enumNotAllowed = new ReservedKeywordValidator("enum");
+    // Enhanced for statements were introduced in Java 5. There must be exactly one declared variable, and the only
+    // allowed modifier is FINAL.
+    final Validator forEachStmt = new SingleNodeTypeValidator<>(ForEachStmt.class, (node, reporter) -> {
+        VariableDeclarationExpr declaration = node.getVariable();
+        // assert that the variable declaration expression has exactly one variable declarator
+        if (declaration.getVariables().size() != 1) {
+            reporter.report(node, "A foreach statement's variable declaration must have exactly one variable " +
+                    "declarator. Given: " + declaration.getVariables().size() + ".");
+        }
+    });
+
+    final Validator enumNotAllowed = new ReservedKeywordValidator("enum");
 
     public Java5Validator() {
         super();
         replace(noGenerics, genericsWithoutDiamondOperator);
         add(noPrimitiveGenericArguments);
         add(enumNotAllowed);
-        
+        add(forEachStmt);
+
         // TODO validate annotations on classes, fields and methods but nowhere else
         // The following is probably too simple.
         remove(noAnnotations);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java7Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java7Validator.java
index 995e836..168ea05 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java7Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java7Validator.java
@@ -1,6 +1,7 @@
 package com.github.javaparser.ast.validator;
 
 import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.SwitchEntry;
 import com.github.javaparser.ast.stmt.TryStmt;
 import com.github.javaparser.ast.type.UnionType;
 
@@ -8,7 +9,7 @@
  * This validator validates according to Java 7 syntax rules.
  */
 public class Java7Validator extends Java6Validator {
-    protected final SingleNodeTypeValidator<TryStmt> tryWithLimitedResources = new SingleNodeTypeValidator<>(TryStmt.class, (n, reporter) -> {
+    final SingleNodeTypeValidator<TryStmt> tryWithLimitedResources = new SingleNodeTypeValidator<>(TryStmt.class, (n, reporter) -> {
         if (n.getCatchClauses().isEmpty()
                 && n.getResources().isEmpty()
                 && !n.getFinallyBlock().isPresent()) {
@@ -20,7 +21,7 @@
             }
         }
     });
-    protected final SingleNodeTypeValidator<UnionType> multiCatch = new SingleNodeTypeValidator<>(UnionType.class, (n, reporter) -> {
+    private final SingleNodeTypeValidator<UnionType> multiCatch = new SingleNodeTypeValidator<>(UnionType.class, (n, reporter) -> {
         // Case "0 elements" is caught elsewhere.
         if (n.getElements().size() == 1) {
             reporter.report(n, "Union type (multi catch) must have at least two elements.");
@@ -31,7 +32,6 @@
         super();
         remove(genericsWithoutDiamondOperator);
         replace(tryWithoutResources, tryWithLimitedResources);
-        remove(noStringsInSwitch);
         remove(noBinaryIntegerLiterals);
         remove(noUnderscoresInIntegerLiterals);
         replace(noMultiCatch, multiCatch);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java8Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java8Validator.java
index e6aca92..026a31d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java8Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java8Validator.java
@@ -7,8 +7,8 @@
  * This validator validates according to Java 7 syntax rules.
  */
 public class Java8Validator extends Java7Validator {
-    protected final Validator modifiersWithoutPrivateInterfaceMethods = new ModifierValidator(true, true, false);
-    protected final Validator defaultMethodsInInterface = new SingleNodeTypeValidator<>(ClassOrInterfaceDeclaration.class,
+    final Validator modifiersWithoutPrivateInterfaceMethods = new ModifierValidator(true, true, false);
+    final Validator defaultMethodsInInterface = new SingleNodeTypeValidator<>(ClassOrInterfaceDeclaration.class,
             (n, reporter) -> {
                 if (n.isInterface()) {
                     n.getMethods().forEach(m -> {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java9Validator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java9Validator.java
index 2175c9a..95de571 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java9Validator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/Java9Validator.java
@@ -1,7 +1,5 @@
 package com.github.javaparser.ast.validator;
 
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
 import com.github.javaparser.ast.stmt.TryStmt;
 import com.github.javaparser.ast.validator.chunks.ModifierValidator;
 import com.github.javaparser.ast.validator.chunks.UnderscoreKeywordValidator;
@@ -10,9 +8,9 @@
  * This validator validates according to Java 9 syntax rules.
  */
 public class Java9Validator extends Java8Validator {
-    protected final Validator underscoreKeywordValidator = new UnderscoreKeywordValidator();
-    protected final Validator modifiers = new ModifierValidator(true, true, true);
-    protected final SingleNodeTypeValidator<TryStmt> tryWithResources = new SingleNodeTypeValidator<>(TryStmt.class, (n, reporter) -> {
+    final Validator underscoreKeywordValidator = new UnderscoreKeywordValidator();
+    final Validator modifiers = new ModifierValidator(true, true, true);
+    final SingleNodeTypeValidator<TryStmt> tryWithResources = new SingleNodeTypeValidator<>(TryStmt.class, (n, reporter) -> {
         if (n.getCatchClauses().isEmpty()
                 && n.getResources().isEmpty()
                 && !n.getFinallyBlock().isPresent()) {
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
deleted file mode 100644
index 0026688..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/NoProblemsValidator.java
+++ /dev/null
@@ -1,16 +0,0 @@
-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 RAW.
- */
-@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/ReservedKeywordValidator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/ReservedKeywordValidator.java
index 51a08bd..ed0ac99 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/ReservedKeywordValidator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/ReservedKeywordValidator.java
@@ -13,7 +13,7 @@
     private final String keyword;
     private final String error;
 
-    public ReservedKeywordValidator(String keyword) {
+    ReservedKeywordValidator(String keyword) {
         this.keyword = keyword;
         error = f("'%s' cannot be used as an identifier as it is a keyword.", keyword);
     }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/CommonValidators.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/CommonValidators.java
index 5e5b791..6324b25 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/CommonValidators.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/CommonValidators.java
@@ -11,8 +11,6 @@
 import com.github.javaparser.metamodel.NodeMetaModel;
 import com.github.javaparser.metamodel.PropertyMetaModel;
 
-import java.util.Optional;
-
 /**
  * Contains validations that are valid for every Java version.
  */
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/ModifierValidator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/ModifierValidator.java
index 0a01c33..17033b5 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/ModifierValidator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/ModifierValidator.java
@@ -4,7 +4,7 @@
 import com.github.javaparser.ast.body.*;
 import com.github.javaparser.ast.expr.LambdaExpr;
 import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.modules.ModuleRequiresStmt;
+import com.github.javaparser.ast.modules.ModuleRequiresDirective;
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers;
 import com.github.javaparser.ast.nodeTypes.NodeWithTokenRange;
 import com.github.javaparser.ast.stmt.CatchClause;
@@ -15,7 +15,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.github.javaparser.ast.Modifier.*;
+import static com.github.javaparser.ast.Modifier.Keyword.*;
 import static java.util.Arrays.asList;
 
 
@@ -23,9 +23,9 @@
  * Verifies that only allowed modifiers are used where modifiers are expected.
  */
 public class ModifierValidator extends VisitorValidator {
-    private final Modifier[] interfaceWithNothingSpecial = new Modifier[]{PUBLIC, PROTECTED, ABSTRACT, FINAL, SYNCHRONIZED, NATIVE, STRICTFP};
-    private final Modifier[] interfaceWithStaticAndDefault = new Modifier[]{PUBLIC, PROTECTED, ABSTRACT, STATIC, FINAL, SYNCHRONIZED, NATIVE, STRICTFP, DEFAULT};
-    private final Modifier[] interfaceWithStaticAndDefaultAndPrivate = new Modifier[]{PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, SYNCHRONIZED, NATIVE, STRICTFP, DEFAULT};
+    private final Modifier.Keyword[] interfaceWithNothingSpecial = new Modifier.Keyword[]{PUBLIC, PROTECTED, ABSTRACT, FINAL, SYNCHRONIZED, NATIVE, STRICTFP};
+    private final Modifier.Keyword[] interfaceWithStaticAndDefault = new Modifier.Keyword[]{PUBLIC, PROTECTED, ABSTRACT, STATIC, FINAL, SYNCHRONIZED, NATIVE, STRICTFP, DEFAULT};
+    private final Modifier.Keyword[] interfaceWithStaticAndDefaultAndPrivate = new Modifier.Keyword[]{PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, SYNCHRONIZED, NATIVE, STRICTFP, DEFAULT};
 
     private final boolean hasStrictfp;
     private final boolean hasDefaultAndStaticInterfaceMethods;
@@ -104,8 +104,8 @@
     public void visit(MethodDeclaration n, ProblemReporter reporter) {
         if (n.isAbstract()) {
             final SeparatedItemStringBuilder builder = new SeparatedItemStringBuilder("Cannot be 'abstract' and also '", "', '", "'.");
-            for (Modifier m : asList(PRIVATE, STATIC, FINAL, NATIVE, STRICTFP, SYNCHRONIZED)) {
-                if (n.getModifiers().contains(m)) {
+            for (Modifier.Keyword m : asList(PRIVATE, STATIC, FINAL, NATIVE, STRICTFP, SYNCHRONIZED)) {
+                if (n.hasModifier(m)) {
                     builder.append(m.asString());
                 }
             }
@@ -156,12 +156,12 @@
     }
 
     @Override
-    public void visit(ModuleRequiresStmt n, ProblemReporter reporter) {
+    public void visit(ModuleRequiresDirective n, ProblemReporter reporter) {
         validateModifiers(n, reporter, TRANSITIVE, STATIC);
         super.visit(n, reporter);
     }
 
-    private <T extends NodeWithModifiers<?> & NodeWithTokenRange<?>> void validateModifiers(T n, ProblemReporter reporter, Modifier... allowedModifiers) {
+    private <T extends NodeWithModifiers<?> & NodeWithTokenRange<?>> void validateModifiers(T n, ProblemReporter reporter, Modifier.Keyword... allowedModifiers) {
         validateAtMostOneOf(n, reporter, PUBLIC, PROTECTED, PRIVATE);
         validateAtMostOneOf(n, reporter, FINAL, ABSTRACT);
         if (hasStrictfp) {
@@ -170,16 +170,16 @@
             allowedModifiers = removeModifierFromArray(STRICTFP, allowedModifiers);
         }
         for (Modifier m : n.getModifiers()) {
-            if (!arrayContains(allowedModifiers, m)) {
-                reporter.report(n, "'%s' is not allowed here.", m.asString());
+            if (!arrayContains(allowedModifiers, m.getKeyword())) {
+                reporter.report(n, "'%s' is not allowed here.", m.getKeyword().asString());
             }
         }
     }
 
-    private Modifier[] removeModifierFromArray(Modifier m, Modifier[] allowedModifiers) {
-        final List<Modifier> newModifiers = new ArrayList<>(asList(allowedModifiers));
+    private Modifier.Keyword[] removeModifierFromArray(Modifier.Keyword m, Modifier.Keyword[] allowedModifiers) {
+        final List<Modifier.Keyword> newModifiers = new ArrayList<>(asList(allowedModifiers));
         newModifiers.remove(m);
-        allowedModifiers = newModifiers.toArray(new Modifier[0]);
+        allowedModifiers = newModifiers.toArray(new Modifier.Keyword[0]);
         return allowedModifiers;
     }
 
@@ -192,16 +192,16 @@
         return false;
     }
 
-    private <T extends NodeWithModifiers<?> & NodeWithTokenRange<?>> void validateAtMostOneOf(T t, ProblemReporter reporter, Modifier... modifiers) {
-        List<Modifier> foundModifiers = new ArrayList<>();
-        for (Modifier m : modifiers) {
-            if (t.getModifiers().contains(m)) {
+    private <T extends NodeWithModifiers<?> & NodeWithTokenRange<?>> void validateAtMostOneOf(T t, ProblemReporter reporter, Modifier.Keyword... modifiers) {
+        List<Modifier.Keyword> foundModifiers = new ArrayList<>();
+        for (Modifier.Keyword m : modifiers) {
+            if (t.hasModifier(m)) {
                 foundModifiers.add(m);
             }
         }
         if (foundModifiers.size() > 1) {
             SeparatedItemStringBuilder builder = new SeparatedItemStringBuilder("Can have only one of '", "', '", "'.");
-            for (Modifier m : foundModifiers) {
+            for (Modifier.Keyword m : foundModifiers) {
                 builder.append(m.asString());
             }
             reporter.report(t, builder.toString());
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/VarValidator.java b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/VarValidator.java
index 19357e8..9f90d68 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/VarValidator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/validator/chunks/VarValidator.java
@@ -3,13 +3,13 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.Parameter;
 import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.expr.ArrayCreationExpr;
+import com.github.javaparser.ast.expr.ArrayInitializerExpr;
 import com.github.javaparser.ast.expr.LambdaExpr;
 import com.github.javaparser.ast.expr.NullLiteralExpr;
 import com.github.javaparser.ast.expr.VariableDeclarationExpr;
 import com.github.javaparser.ast.stmt.ExpressionStmt;
 import com.github.javaparser.ast.stmt.ForStmt;
-import com.github.javaparser.ast.stmt.ForeachStmt;
+import com.github.javaparser.ast.stmt.ForEachStmt;
 import com.github.javaparser.ast.type.VarType;
 import com.github.javaparser.ast.validator.ProblemReporter;
 import com.github.javaparser.ast.validator.TypedValidator;
@@ -26,12 +26,12 @@
     @Override
     public void accept(VarType node, ProblemReporter reporter) {
         // All allowed locations are within a VariableDeclaration inside a VariableDeclarationExpr inside something else.
-        Optional<VariableDeclarator> variableDeclarator = node.findParent(VariableDeclarator.class);
+        Optional<VariableDeclarator> variableDeclarator = node.findAncestor(VariableDeclarator.class);
         if (!variableDeclarator.isPresent()) {
             // Java 11's var in lambda's
             if (varAllowedInLambdaParameters) {
                 boolean valid = node
-                        .findParent(Parameter.class)
+                        .findAncestor(Parameter.class)
                         .flatMap(Node::getParentNode)
                         .map((Node p) -> p instanceof LambdaExpr).orElse(false);
                 if (valid) {
@@ -42,6 +42,9 @@
             return;
         }
         variableDeclarator.ifPresent(vd -> {
+            if (vd.getType().isArrayType()) {
+                reporter.report(vd, "\"var\" cannot have extra array brackets.");
+            }
             Optional<Node> variableDeclarationExpr = vd.getParentNode();
             if (!variableDeclarationExpr.isPresent()) {
                 reportIllegalPosition(node, reporter);
@@ -62,7 +65,7 @@
                     return;
                 }
                 container.ifPresent(c -> {
-                    boolean positionIsFine = c instanceof ForStmt || c instanceof ForeachStmt || c instanceof ExpressionStmt;
+                    boolean positionIsFine = c instanceof ForStmt || c instanceof ForEachStmt || c instanceof ExpressionStmt;
                     if (!positionIsFine) {
                         reportIllegalPosition(node, reporter);
                     }
@@ -75,7 +78,7 @@
                             if (initializer instanceof NullLiteralExpr) {
                                 reporter.report(node, "\"var\" cannot infer type from just null.");
                             }
-                            if (initializer instanceof ArrayCreationExpr) {
+                            if (initializer instanceof ArrayInitializerExpr) {
                                 reporter.report(node, "\"var\" cannot infer array types.");
                             }
                         });
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 4ae343a..62b1f90 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
@@ -22,13 +22,15 @@
 
 import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.comments.*;
+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.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
 import java.util.Optional;
-import javax.annotation.Generated;
 
 /**
  * A visitor that clones (copies) a node and all its children.
@@ -44,7 +46,10 @@
         NodeList<TypeDeclaration<?>> types = cloneList(n.getTypes(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         CompilationUnit r = new CompilationUnit(n.getTokenRange().orElse(null), packageDeclaration, imports, types, module);
+        n.getStorage().ifPresent(s -> r.setStorage(s.getPath(), s.getEncoding()));
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
@@ -56,11 +61,12 @@
         Comment comment = cloneNode(n.getComment(), arg);
         PackageDeclaration r = new PackageDeclaration(n.getTokenRange().orElse(null), annotations, name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final TypeParameter n, final Object arg) {
         SimpleName name = cloneNode(n.getName(), arg);
         NodeList<ClassOrInterfaceType> typeBound = cloneList(n.getTypeBound(), arg);
@@ -68,58 +74,65 @@
         Comment comment = cloneNode(n.getComment(), arg);
         TypeParameter r = new TypeParameter(n.getTokenRange().orElse(null), name, typeBound, annotations);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final LineComment n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         LineComment r = new LineComment(n.getTokenRange().orElse(null), n.getContent());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final BlockComment n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         BlockComment r = new BlockComment(n.getTokenRange().orElse(null), n.getContent());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ClassOrInterfaceDeclaration n, final Object arg) {
         NodeList<ClassOrInterfaceType> extendedTypes = cloneList(n.getExtendedTypes(), arg);
         NodeList<ClassOrInterfaceType> implementedTypes = cloneList(n.getImplementedTypes(), arg);
         NodeList<TypeParameter> typeParameters = cloneList(n.getTypeParameters(), arg);
         NodeList<BodyDeclaration<?>> members = cloneList(n.getMembers(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ClassOrInterfaceDeclaration r = new ClassOrInterfaceDeclaration(n.getTokenRange().orElse(null), n.getModifiers(), annotations, n.isInterface(), name, typeParameters, extendedTypes, implementedTypes, members);
+        ClassOrInterfaceDeclaration r = new ClassOrInterfaceDeclaration(n.getTokenRange().orElse(null), modifiers, annotations, n.isInterface(), name, typeParameters, extendedTypes, implementedTypes, members);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final EnumDeclaration n, final Object arg) {
         NodeList<EnumConstantDeclaration> entries = cloneList(n.getEntries(), arg);
         NodeList<ClassOrInterfaceType> implementedTypes = cloneList(n.getImplementedTypes(), arg);
         NodeList<BodyDeclaration<?>> members = cloneList(n.getMembers(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        EnumDeclaration r = new EnumDeclaration(n.getTokenRange().orElse(null), n.getModifiers(), annotations, name, implementedTypes, entries, members);
+        EnumDeclaration r = new EnumDeclaration(n.getTokenRange().orElse(null), modifiers, annotations, name, implementedTypes, entries, members);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final EnumConstantDeclaration n, final Object arg) {
         NodeList<Expression> arguments = cloneList(n.getArguments(), arg);
         NodeList<BodyDeclaration<?>> classBody = cloneList(n.getClassBody(), arg);
@@ -128,47 +141,54 @@
         Comment comment = cloneNode(n.getComment(), arg);
         EnumConstantDeclaration r = new EnumConstantDeclaration(n.getTokenRange().orElse(null), annotations, name, arguments, classBody);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final AnnotationDeclaration n, final Object arg) {
         NodeList<BodyDeclaration<?>> members = cloneList(n.getMembers(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        AnnotationDeclaration r = new AnnotationDeclaration(n.getTokenRange().orElse(null), n.getModifiers(), annotations, name, members);
+        AnnotationDeclaration r = new AnnotationDeclaration(n.getTokenRange().orElse(null), modifiers, annotations, name, members);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final AnnotationMemberDeclaration n, final Object arg) {
         Expression defaultValue = cloneNode(n.getDefaultValue(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
         Type type = cloneNode(n.getType(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        AnnotationMemberDeclaration r = new AnnotationMemberDeclaration(n.getTokenRange().orElse(null), n.getModifiers(), annotations, type, name, defaultValue);
+        AnnotationMemberDeclaration r = new AnnotationMemberDeclaration(n.getTokenRange().orElse(null), modifiers, annotations, type, name, defaultValue);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final FieldDeclaration n, final Object arg) {
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         NodeList<VariableDeclarator> variables = cloneList(n.getVariables(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        FieldDeclaration r = new FieldDeclaration(n.getTokenRange().orElse(null), n.getModifiers(), annotations, variables);
+        FieldDeclaration r = new FieldDeclaration(n.getTokenRange().orElse(null), modifiers, annotations, variables);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final VariableDeclarator n, final Object arg) {
         Expression initializer = cloneNode(n.getInitializer(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
@@ -176,13 +196,15 @@
         Comment comment = cloneNode(n.getComment(), arg);
         VariableDeclarator r = new VariableDeclarator(n.getTokenRange().orElse(null), type, name, initializer);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ConstructorDeclaration n, final Object arg) {
         BlockStmt body = cloneNode(n.getBody(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
         NodeList<Parameter> parameters = cloneList(n.getParameters(), arg);
         ReceiverParameter receiverParameter = cloneNode(n.getReceiverParameter(), arg);
@@ -190,16 +212,18 @@
         NodeList<TypeParameter> typeParameters = cloneList(n.getTypeParameters(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ConstructorDeclaration r = new ConstructorDeclaration(n.getTokenRange().orElse(null), n.getModifiers(), annotations, typeParameters, name, parameters, thrownExceptions, body, receiverParameter);
+        ConstructorDeclaration r = new ConstructorDeclaration(n.getTokenRange().orElse(null), modifiers, annotations, typeParameters, name, parameters, thrownExceptions, body, receiverParameter);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final MethodDeclaration n, final Object arg) {
         BlockStmt body = cloneNode(n.getBody(), arg);
         Type type = cloneNode(n.getType(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
         NodeList<Parameter> parameters = cloneList(n.getParameters(), arg);
         ReceiverParameter receiverParameter = cloneNode(n.getReceiverParameter(), arg);
@@ -207,46 +231,51 @@
         NodeList<TypeParameter> typeParameters = cloneList(n.getTypeParameters(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        MethodDeclaration r = new MethodDeclaration(n.getTokenRange().orElse(null), n.getModifiers(), annotations, typeParameters, type, name, parameters, thrownExceptions, body, receiverParameter);
+        MethodDeclaration r = new MethodDeclaration(n.getTokenRange().orElse(null), modifiers, annotations, typeParameters, type, name, parameters, thrownExceptions, body, receiverParameter);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final Parameter n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
         Type type = cloneNode(n.getType(), arg);
         NodeList<AnnotationExpr> varArgsAnnotations = cloneList(n.getVarArgsAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        Parameter r = new Parameter(n.getTokenRange().orElse(null), n.getModifiers(), annotations, type, n.isVarArgs(), varArgsAnnotations, name);
+        Parameter r = new Parameter(n.getTokenRange().orElse(null), modifiers, annotations, type, n.isVarArgs(), varArgsAnnotations, name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final InitializerDeclaration n, final Object arg) {
         BlockStmt body = cloneNode(n.getBody(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         InitializerDeclaration r = new InitializerDeclaration(n.getTokenRange().orElse(null), n.isStatic(), body);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final JavadocComment n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         JavadocComment r = new JavadocComment(n.getTokenRange().orElse(null), n.getContent());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ClassOrInterfaceType n, final Object arg) {
         SimpleName name = cloneNode(n.getName(), arg);
         ClassOrInterfaceType scope = cloneNode(n.getScope(), arg);
@@ -255,75 +284,82 @@
         Comment comment = cloneNode(n.getComment(), arg);
         ClassOrInterfaceType r = new ClassOrInterfaceType(n.getTokenRange().orElse(null), scope, name, typeArguments, annotations);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final PrimitiveType n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         PrimitiveType r = new PrimitiveType(n.getTokenRange().orElse(null), n.getType(), annotations);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ArrayType n, final Object arg) {
         Type componentType = cloneNode(n.getComponentType(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ArrayType r = new ArrayType(n.getTokenRange().orElse(null), componentType, n.getOrigin(), annotations);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ArrayCreationLevel n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Expression dimension = cloneNode(n.getDimension(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ArrayCreationLevel r = new ArrayCreationLevel(n.getTokenRange().orElse(null), dimension, annotations);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final IntersectionType n, final Object arg) {
         NodeList<ReferenceType> elements = cloneList(n.getElements(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         IntersectionType r = new IntersectionType(n.getTokenRange().orElse(null), elements);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final UnionType n, final Object arg) {
         NodeList<ReferenceType> elements = cloneList(n.getElements(), arg);
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         UnionType r = new UnionType(n.getTokenRange().orElse(null), elements);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final VoidType n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         VoidType r = new VoidType(n.getTokenRange().orElse(null));
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final WildcardType n, final Object arg) {
         ReferenceType extendedType = cloneNode(n.getExtendedType(), arg);
         ReferenceType superType = cloneNode(n.getSuperType(), arg);
@@ -331,32 +367,35 @@
         Comment comment = cloneNode(n.getComment(), arg);
         WildcardType r = new WildcardType(n.getTokenRange().orElse(null), extendedType, superType, annotations);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final UnknownType n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         UnknownType r = new UnknownType(n.getTokenRange().orElse(null));
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ArrayAccessExpr n, final Object arg) {
         Expression index = cloneNode(n.getIndex(), arg);
         Expression name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ArrayAccessExpr r = new ArrayAccessExpr(n.getTokenRange().orElse(null), name, index);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ArrayCreationExpr n, final Object arg) {
         Type elementType = cloneNode(n.getElementType(), arg);
         ArrayInitializerExpr initializer = cloneNode(n.getInitializer(), arg);
@@ -364,64 +403,70 @@
         Comment comment = cloneNode(n.getComment(), arg);
         ArrayCreationExpr r = new ArrayCreationExpr(n.getTokenRange().orElse(null), elementType, levels, initializer);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ArrayInitializerExpr n, final Object arg) {
         NodeList<Expression> values = cloneList(n.getValues(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ArrayInitializerExpr r = new ArrayInitializerExpr(n.getTokenRange().orElse(null), values);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final AssignExpr n, final Object arg) {
         Expression target = cloneNode(n.getTarget(), arg);
         Expression value = cloneNode(n.getValue(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         AssignExpr r = new AssignExpr(n.getTokenRange().orElse(null), target, value, n.getOperator());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final BinaryExpr n, final Object arg) {
         Expression left = cloneNode(n.getLeft(), arg);
         Expression right = cloneNode(n.getRight(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         BinaryExpr r = new BinaryExpr(n.getTokenRange().orElse(null), left, right, n.getOperator());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final CastExpr n, final Object arg) {
         Expression expression = cloneNode(n.getExpression(), arg);
         Type type = cloneNode(n.getType(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         CastExpr r = new CastExpr(n.getTokenRange().orElse(null), type, expression);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ClassExpr n, final Object arg) {
         Type type = cloneNode(n.getType(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ClassExpr r = new ClassExpr(n.getTokenRange().orElse(null), type);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ConditionalExpr n, final Object arg) {
         Expression condition = cloneNode(n.getCondition(), arg);
         Expression elseExpr = cloneNode(n.getElseExpr(), arg);
@@ -429,21 +474,23 @@
         Comment comment = cloneNode(n.getComment(), arg);
         ConditionalExpr r = new ConditionalExpr(n.getTokenRange().orElse(null), condition, thenExpr, elseExpr);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final EnclosedExpr n, final Object arg) {
         Expression inner = cloneNode(n.getInner(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         EnclosedExpr r = new EnclosedExpr(n.getTokenRange().orElse(null), inner);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final FieldAccessExpr n, final Object arg) {
         SimpleName name = cloneNode(n.getName(), arg);
         Expression scope = cloneNode(n.getScope(), arg);
@@ -451,85 +498,94 @@
         Comment comment = cloneNode(n.getComment(), arg);
         FieldAccessExpr r = new FieldAccessExpr(n.getTokenRange().orElse(null), scope, typeArguments, name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final InstanceOfExpr n, final Object arg) {
         Expression expression = cloneNode(n.getExpression(), arg);
         ReferenceType type = cloneNode(n.getType(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         InstanceOfExpr r = new InstanceOfExpr(n.getTokenRange().orElse(null), expression, type);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final StringLiteralExpr n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         StringLiteralExpr r = new StringLiteralExpr(n.getTokenRange().orElse(null), n.getValue());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final IntegerLiteralExpr n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         IntegerLiteralExpr r = new IntegerLiteralExpr(n.getTokenRange().orElse(null), n.getValue());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final LongLiteralExpr n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         LongLiteralExpr r = new LongLiteralExpr(n.getTokenRange().orElse(null), n.getValue());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final CharLiteralExpr n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         CharLiteralExpr r = new CharLiteralExpr(n.getTokenRange().orElse(null), n.getValue());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final DoubleLiteralExpr n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         DoubleLiteralExpr r = new DoubleLiteralExpr(n.getTokenRange().orElse(null), n.getValue());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final BooleanLiteralExpr n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         BooleanLiteralExpr r = new BooleanLiteralExpr(n.getTokenRange().orElse(null), n.getValue());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final NullLiteralExpr n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         NullLiteralExpr r = new NullLiteralExpr(n.getTokenRange().orElse(null));
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final MethodCallExpr n, final Object arg) {
         NodeList<Expression> arguments = cloneList(n.getArguments(), arg);
         SimpleName name = cloneNode(n.getName(), arg);
@@ -538,21 +594,23 @@
         Comment comment = cloneNode(n.getComment(), arg);
         MethodCallExpr r = new MethodCallExpr(n.getTokenRange().orElse(null), scope, typeArguments, name, arguments);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final NameExpr n, final Object arg) {
         SimpleName name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         NameExpr r = new NameExpr(n.getTokenRange().orElse(null), name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ObjectCreationExpr n, final Object arg) {
         NodeList<BodyDeclaration<?>> anonymousClassBody = cloneList(n.getAnonymousClassBody().orElse(null), arg);
         NodeList<Expression> arguments = cloneList(n.getArguments(), arg);
@@ -562,115 +620,126 @@
         Comment comment = cloneNode(n.getComment(), arg);
         ObjectCreationExpr r = new ObjectCreationExpr(n.getTokenRange().orElse(null), scope, type, typeArguments, arguments, anonymousClassBody);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final Name n, final Object arg) {
-        NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Name qualifier = cloneNode(n.getQualifier(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        Name r = new Name(n.getTokenRange().orElse(null), qualifier, n.getIdentifier(), annotations);
+        Name r = new Name(n.getTokenRange().orElse(null), qualifier, n.getIdentifier());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final SimpleName n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         SimpleName r = new SimpleName(n.getTokenRange().orElse(null), n.getIdentifier());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ThisExpr n, final Object arg) {
-        Expression classExpr = cloneNode(n.getClassExpr(), arg);
+        Name typeName = cloneNode(n.getTypeName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ThisExpr r = new ThisExpr(n.getTokenRange().orElse(null), classExpr);
+        ThisExpr r = new ThisExpr(n.getTokenRange().orElse(null), typeName);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final SuperExpr n, final Object arg) {
-        Expression classExpr = cloneNode(n.getClassExpr(), arg);
+        Name typeName = cloneNode(n.getTypeName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        SuperExpr r = new SuperExpr(n.getTokenRange().orElse(null), classExpr);
+        SuperExpr r = new SuperExpr(n.getTokenRange().orElse(null), typeName);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final UnaryExpr n, final Object arg) {
         Expression expression = cloneNode(n.getExpression(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         UnaryExpr r = new UnaryExpr(n.getTokenRange().orElse(null), expression, n.getOperator());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final VariableDeclarationExpr n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         NodeList<VariableDeclarator> variables = cloneList(n.getVariables(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        VariableDeclarationExpr r = new VariableDeclarationExpr(n.getTokenRange().orElse(null), n.getModifiers(), annotations, variables);
+        VariableDeclarationExpr r = new VariableDeclarationExpr(n.getTokenRange().orElse(null), modifiers, annotations, variables);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final MarkerAnnotationExpr n, final Object arg) {
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         MarkerAnnotationExpr r = new MarkerAnnotationExpr(n.getTokenRange().orElse(null), name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final SingleMemberAnnotationExpr n, final Object arg) {
         Expression memberValue = cloneNode(n.getMemberValue(), arg);
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         SingleMemberAnnotationExpr r = new SingleMemberAnnotationExpr(n.getTokenRange().orElse(null), name, memberValue);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final NormalAnnotationExpr n, final Object arg) {
         NodeList<MemberValuePair> pairs = cloneList(n.getPairs(), arg);
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         NormalAnnotationExpr r = new NormalAnnotationExpr(n.getTokenRange().orElse(null), name, pairs);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final MemberValuePair n, final Object arg) {
         SimpleName name = cloneNode(n.getName(), arg);
         Expression value = cloneNode(n.getValue(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         MemberValuePair r = new MemberValuePair(n.getTokenRange().orElse(null), name, value);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ExplicitConstructorInvocationStmt n, final Object arg) {
         NodeList<Expression> arguments = cloneList(n.getArguments(), arg);
         Expression expression = cloneNode(n.getExpression(), arg);
@@ -678,114 +747,125 @@
         Comment comment = cloneNode(n.getComment(), arg);
         ExplicitConstructorInvocationStmt r = new ExplicitConstructorInvocationStmt(n.getTokenRange().orElse(null), typeArguments, n.isThis(), expression, arguments);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final LocalClassDeclarationStmt n, final Object arg) {
         ClassOrInterfaceDeclaration classDeclaration = cloneNode(n.getClassDeclaration(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         LocalClassDeclarationStmt r = new LocalClassDeclarationStmt(n.getTokenRange().orElse(null), classDeclaration);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final AssertStmt n, final Object arg) {
         Expression check = cloneNode(n.getCheck(), arg);
         Expression message = cloneNode(n.getMessage(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         AssertStmt r = new AssertStmt(n.getTokenRange().orElse(null), check, message);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final BlockStmt n, final Object arg) {
         NodeList<Statement> statements = cloneList(n.getStatements(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         BlockStmt r = new BlockStmt(n.getTokenRange().orElse(null), statements);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final LabeledStmt n, final Object arg) {
         SimpleName label = cloneNode(n.getLabel(), arg);
         Statement statement = cloneNode(n.getStatement(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         LabeledStmt r = new LabeledStmt(n.getTokenRange().orElse(null), label, statement);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final EmptyStmt n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         EmptyStmt r = new EmptyStmt(n.getTokenRange().orElse(null));
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ExpressionStmt n, final Object arg) {
         Expression expression = cloneNode(n.getExpression(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ExpressionStmt r = new ExpressionStmt(n.getTokenRange().orElse(null), expression);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final SwitchStmt n, final Object arg) {
-        NodeList<SwitchEntryStmt> entries = cloneList(n.getEntries(), arg);
+        NodeList<SwitchEntry> entries = cloneList(n.getEntries(), arg);
         Expression selector = cloneNode(n.getSelector(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         SwitchStmt r = new SwitchStmt(n.getTokenRange().orElse(null), selector, entries);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
-    public Visitable visit(final SwitchEntryStmt n, final Object arg) {
-        Expression label = cloneNode(n.getLabel(), arg);
+    public Visitable visit(final SwitchEntry n, final Object arg) {
+        NodeList<Expression> labels = cloneList(n.getLabels(), arg);
         NodeList<Statement> statements = cloneList(n.getStatements(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        SwitchEntryStmt r = new SwitchEntryStmt(n.getTokenRange().orElse(null), label, statements);
+        SwitchEntry r = new SwitchEntry(n.getTokenRange().orElse(null), labels, n.getType(), statements);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final BreakStmt n, final Object arg) {
-        SimpleName label = cloneNode(n.getLabel(), arg);
+        Expression value = cloneNode(n.getValue(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        BreakStmt r = new BreakStmt(n.getTokenRange().orElse(null), label);
+        BreakStmt r = new BreakStmt(n.getTokenRange().orElse(null), value);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ReturnStmt n, final Object arg) {
         Expression expression = cloneNode(n.getExpression(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ReturnStmt r = new ReturnStmt(n.getTokenRange().orElse(null), expression);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final IfStmt n, final Object arg) {
         Expression condition = cloneNode(n.getCondition(), arg);
         Statement elseStmt = cloneNode(n.getElseStmt(), arg);
@@ -793,55 +873,60 @@
         Comment comment = cloneNode(n.getComment(), arg);
         IfStmt r = new IfStmt(n.getTokenRange().orElse(null), condition, thenStmt, elseStmt);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final WhileStmt n, final Object arg) {
         Statement body = cloneNode(n.getBody(), arg);
         Expression condition = cloneNode(n.getCondition(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         WhileStmt r = new WhileStmt(n.getTokenRange().orElse(null), condition, body);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ContinueStmt n, final Object arg) {
         SimpleName label = cloneNode(n.getLabel(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ContinueStmt r = new ContinueStmt(n.getTokenRange().orElse(null), label);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final DoStmt n, final Object arg) {
         Statement body = cloneNode(n.getBody(), arg);
         Expression condition = cloneNode(n.getCondition(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         DoStmt r = new DoStmt(n.getTokenRange().orElse(null), body, condition);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
-    public Visitable visit(final ForeachStmt n, final Object arg) {
+    public Visitable visit(final ForEachStmt n, final Object arg) {
         Statement body = cloneNode(n.getBody(), arg);
         Expression iterable = cloneNode(n.getIterable(), arg);
         VariableDeclarationExpr variable = cloneNode(n.getVariable(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ForeachStmt r = new ForeachStmt(n.getTokenRange().orElse(null), variable, iterable, body);
+        ForEachStmt r = new ForEachStmt(n.getTokenRange().orElse(null), variable, iterable, body);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ForStmt n, final Object arg) {
         Statement body = cloneNode(n.getBody(), arg);
         Expression compare = cloneNode(n.getCompare(), arg);
@@ -850,32 +935,35 @@
         Comment comment = cloneNode(n.getComment(), arg);
         ForStmt r = new ForStmt(n.getTokenRange().orElse(null), initialization, compare, update, body);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ThrowStmt n, final Object arg) {
         Expression expression = cloneNode(n.getExpression(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ThrowStmt r = new ThrowStmt(n.getTokenRange().orElse(null), expression);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final SynchronizedStmt n, final Object arg) {
         BlockStmt body = cloneNode(n.getBody(), arg);
         Expression expression = cloneNode(n.getExpression(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         SynchronizedStmt r = new SynchronizedStmt(n.getTokenRange().orElse(null), expression, body);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final TryStmt n, final Object arg) {
         NodeList<CatchClause> catchClauses = cloneList(n.getCatchClauses(), arg);
         BlockStmt finallyBlock = cloneNode(n.getFinallyBlock(), arg);
@@ -884,49 +972,55 @@
         Comment comment = cloneNode(n.getComment(), arg);
         TryStmt r = new TryStmt(n.getTokenRange().orElse(null), resources, tryBlock, catchClauses, finallyBlock);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final CatchClause n, final Object arg) {
         BlockStmt body = cloneNode(n.getBody(), arg);
         Parameter parameter = cloneNode(n.getParameter(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         CatchClause r = new CatchClause(n.getTokenRange().orElse(null), parameter, body);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final LambdaExpr n, final Object arg) {
         Statement body = cloneNode(n.getBody(), arg);
         NodeList<Parameter> parameters = cloneList(n.getParameters(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         LambdaExpr r = new LambdaExpr(n.getTokenRange().orElse(null), parameters, body, n.isEnclosingParameters());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final MethodReferenceExpr n, final Object arg) {
         Expression scope = cloneNode(n.getScope(), arg);
         NodeList<Type> typeArguments = cloneList(n.getTypeArguments().orElse(null), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         MethodReferenceExpr r = new MethodReferenceExpr(n.getTokenRange().orElse(null), scope, typeArguments, n.getIdentifier());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final TypeExpr n, final Object arg) {
         Type type = cloneNode(n.getType(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         TypeExpr r = new TypeExpr(n.getTokenRange().orElse(null), type);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
@@ -943,34 +1037,38 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Node visit(final ImportDeclaration n, final Object arg) {
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
         ImportDeclaration r = new ImportDeclaration(n.getTokenRange().orElse(null), name, n.isStatic(), n.isAsterisk());
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ModuleDeclaration n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
-        NodeList<ModuleStmt> moduleStmts = cloneList(n.getModuleStmts(), arg);
+        NodeList<ModuleDirective> directives = cloneList(n.getDirectives(), arg);
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ModuleDeclaration r = new ModuleDeclaration(n.getTokenRange().orElse(null), annotations, name, n.isOpen(), moduleStmts);
+        ModuleDeclaration r = new ModuleDeclaration(n.getTokenRange().orElse(null), annotations, name, n.isOpen(), directives);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
-    public Visitable visit(final ModuleRequiresStmt n, final Object arg) {
+    public Visitable visit(final ModuleRequiresDirective n, final Object arg) {
+        NodeList<Modifier> modifiers = cloneList(n.getModifiers(), arg);
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ModuleRequiresStmt r = new ModuleRequiresStmt(n.getTokenRange().orElse(null), n.getModifiers(), name);
+        ModuleRequiresDirective r = new ModuleRequiresDirective(n.getTokenRange().orElse(null), modifiers, name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
@@ -1006,59 +1104,63 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
-    public Visitable visit(final ModuleExportsStmt n, final Object arg) {
+    public Visitable visit(final ModuleExportsDirective n, final Object arg) {
         NodeList<Name> moduleNames = cloneList(n.getModuleNames(), arg);
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ModuleExportsStmt r = new ModuleExportsStmt(n.getTokenRange().orElse(null), name, moduleNames);
+        ModuleExportsDirective r = new ModuleExportsDirective(n.getTokenRange().orElse(null), name, moduleNames);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
-    public Visitable visit(final ModuleProvidesStmt n, final Object arg) {
-        Type type = cloneNode(n.getType(), arg);
-        NodeList<Type> withTypes = cloneList(n.getWithTypes(), arg);
+    public Visitable visit(final ModuleProvidesDirective n, final Object arg) {
+        Name name = cloneNode(n.getName(), arg);
+        NodeList<Name> with = cloneList(n.getWith(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ModuleProvidesStmt r = new ModuleProvidesStmt(n.getTokenRange().orElse(null), type, withTypes);
+        ModuleProvidesDirective r = new ModuleProvidesDirective(n.getTokenRange().orElse(null), name, with);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
-    public Visitable visit(final ModuleUsesStmt n, final Object arg) {
-        Type type = cloneNode(n.getType(), arg);
+    public Visitable visit(final ModuleUsesDirective n, final Object arg) {
+        Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ModuleUsesStmt r = new ModuleUsesStmt(n.getTokenRange().orElse(null), type);
+        ModuleUsesDirective r = new ModuleUsesDirective(n.getTokenRange().orElse(null), name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
-    public Visitable visit(final ModuleOpensStmt n, final Object arg) {
+    public Visitable visit(final ModuleOpensDirective n, final Object arg) {
         NodeList<Name> moduleNames = cloneList(n.getModuleNames(), arg);
         Name name = cloneNode(n.getName(), arg);
         Comment comment = cloneNode(n.getComment(), arg);
-        ModuleOpensStmt r = new ModuleOpensStmt(n.getTokenRange().orElse(null), name, moduleNames);
+        ModuleOpensDirective r = new ModuleOpensDirective(n.getTokenRange().orElse(null), name, moduleNames);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final UnparsableStmt n, final Object arg) {
         Comment comment = cloneNode(n.getComment(), arg);
         UnparsableStmt r = new UnparsableStmt(n.getTokenRange().orElse(null));
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.CloneVisitorGenerator")
     public Visitable visit(final ReceiverParameter n, final Object arg) {
         NodeList<AnnotationExpr> annotations = cloneList(n.getAnnotations(), arg);
         Name name = cloneNode(n.getName(), arg);
@@ -1066,6 +1168,8 @@
         Comment comment = cloneNode(n.getComment(), arg);
         ReceiverParameter r = new ReceiverParameter(n.getTokenRange().orElse(null), annotations, type, name);
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
 
@@ -1075,6 +1179,36 @@
         Comment comment = cloneNode(n.getComment(), arg);
         VarType r = new VarType(n.getTokenRange().orElse(null));
         r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
         return r;
     }
+
+    @Override
+    public Visitable visit(final Modifier n, final Object arg) {
+        Comment comment = cloneNode(n.getComment(), arg);
+        Modifier r = new Modifier(n.getTokenRange().orElse(null), n.getKeyword());
+        r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
+        return r;
+    }
+
+    @Override
+    public Visitable visit(final SwitchExpr n, final Object arg) {
+        NodeList<SwitchEntry> entries = cloneList(n.getEntries(), arg);
+        Expression selector = cloneNode(n.getSelector(), arg);
+        Comment comment = cloneNode(n.getComment(), arg);
+        SwitchExpr r = new SwitchExpr(n.getTokenRange().orElse(null), selector, entries);
+        r.setComment(comment);
+        n.getOrphanComments().stream().map(Comment::clone).forEach(r::addOrphanComment);
+        copyData(n, r);
+        return r;
+    }
+
+    private void copyData(Node source, Node destination) {
+        for (DataKey dataKey : source.getDataKeys()) {
+            destination.setData(dataKey, source.getData(dataKey));
+        }
+    }
 }
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 2062185..5bb2632 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
@@ -31,7 +31,6 @@
 import com.github.javaparser.ast.type.*;
 import java.util.List;
 import java.util.Optional;
-import javax.annotation.Generated;
 
 /**
  * A visitor that calculates deep node equality by comparing all properties and child nodes of the node.
@@ -131,7 +130,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final CompilationUnit n, final Visitable arg) {
         final CompilationUnit n2 = (CompilationUnit) arg;
         if (!nodesEquals(n.getImports(), n2.getImports()))
@@ -148,7 +146,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final PackageDeclaration n, final Visitable arg) {
         final PackageDeclaration n2 = (PackageDeclaration) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -161,7 +158,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final TypeParameter n, final Visitable arg) {
         final TypeParameter n2 = (TypeParameter) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -176,7 +172,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final LineComment n, final Visitable arg) {
         final LineComment n2 = (LineComment) arg;
         if (!objEquals(n.getContent(), n2.getContent()))
@@ -187,7 +182,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final BlockComment n, final Visitable arg) {
         final BlockComment n2 = (BlockComment) arg;
         if (!objEquals(n.getContent(), n2.getContent()))
@@ -198,7 +192,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ClassOrInterfaceDeclaration n, final Visitable arg) {
         final ClassOrInterfaceDeclaration n2 = (ClassOrInterfaceDeclaration) arg;
         if (!nodesEquals(n.getExtendedTypes(), n2.getExtendedTypes()))
@@ -211,7 +204,7 @@
             return false;
         if (!nodesEquals(n.getMembers(), n2.getMembers()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -223,7 +216,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final EnumDeclaration n, final Visitable arg) {
         final EnumDeclaration n2 = (EnumDeclaration) arg;
         if (!nodesEquals(n.getEntries(), n2.getEntries()))
@@ -232,7 +224,7 @@
             return false;
         if (!nodesEquals(n.getMembers(), n2.getMembers()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -244,7 +236,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final EnumConstantDeclaration n, final Visitable arg) {
         final EnumConstantDeclaration n2 = (EnumConstantDeclaration) arg;
         if (!nodesEquals(n.getArguments(), n2.getArguments()))
@@ -261,12 +252,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final AnnotationDeclaration n, final Visitable arg) {
         final AnnotationDeclaration n2 = (AnnotationDeclaration) arg;
         if (!nodesEquals(n.getMembers(), n2.getMembers()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -278,12 +268,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final AnnotationMemberDeclaration n, final Visitable arg) {
         final AnnotationMemberDeclaration n2 = (AnnotationMemberDeclaration) arg;
         if (!nodeEquals(n.getDefaultValue(), n2.getDefaultValue()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -297,10 +286,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final FieldDeclaration n, final Visitable arg) {
         final FieldDeclaration n2 = (FieldDeclaration) arg;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodesEquals(n.getVariables(), n2.getVariables()))
             return false;
@@ -312,7 +300,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final VariableDeclarator n, final Visitable arg) {
         final VariableDeclarator n2 = (VariableDeclarator) arg;
         if (!nodeEquals(n.getInitializer(), n2.getInitializer()))
@@ -327,12 +314,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ConstructorDeclaration n, final Visitable arg) {
         final ConstructorDeclaration n2 = (ConstructorDeclaration) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -352,14 +338,13 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final MethodDeclaration n, final Visitable arg) {
         final MethodDeclaration n2 = (MethodDeclaration) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
             return false;
         if (!nodeEquals(n.getType(), n2.getType()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -379,14 +364,13 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final Parameter n, final Visitable arg) {
         final Parameter n2 = (Parameter) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
             return false;
         if (!objEquals(n.isVarArgs(), n2.isVarArgs()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -400,7 +384,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final InitializerDeclaration n, final Visitable arg) {
         final InitializerDeclaration n2 = (InitializerDeclaration) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -415,7 +398,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final JavadocComment n, final Visitable arg) {
         final JavadocComment n2 = (JavadocComment) arg;
         if (!objEquals(n.getContent(), n2.getContent()))
@@ -426,7 +408,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ClassOrInterfaceType n, final Visitable arg) {
         final ClassOrInterfaceType n2 = (ClassOrInterfaceType) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -443,7 +424,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final PrimitiveType n, final Visitable arg) {
         final PrimitiveType n2 = (PrimitiveType) arg;
         if (!objEquals(n.getType(), n2.getType()))
@@ -456,7 +436,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ArrayType n, final Visitable arg) {
         final ArrayType n2 = (ArrayType) arg;
         if (!nodeEquals(n.getComponentType(), n2.getComponentType()))
@@ -471,7 +450,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ArrayCreationLevel n, final Visitable arg) {
         final ArrayCreationLevel n2 = (ArrayCreationLevel) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -484,7 +462,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final IntersectionType n, final Visitable arg) {
         final IntersectionType n2 = (IntersectionType) arg;
         if (!nodesEquals(n.getElements(), n2.getElements()))
@@ -497,7 +474,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final UnionType n, final Visitable arg) {
         final UnionType n2 = (UnionType) arg;
         if (!nodesEquals(n.getElements(), n2.getElements()))
@@ -510,7 +486,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final VoidType n, final Visitable arg) {
         final VoidType n2 = (VoidType) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -521,7 +496,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final WildcardType n, final Visitable arg) {
         final WildcardType n2 = (WildcardType) arg;
         if (!nodeEquals(n.getExtendedType(), n2.getExtendedType()))
@@ -536,7 +510,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final UnknownType n, final Visitable arg) {
         final UnknownType n2 = (UnknownType) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -547,7 +520,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ArrayAccessExpr n, final Visitable arg) {
         final ArrayAccessExpr n2 = (ArrayAccessExpr) arg;
         if (!nodeEquals(n.getIndex(), n2.getIndex()))
@@ -560,7 +532,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ArrayCreationExpr n, final Visitable arg) {
         final ArrayCreationExpr n2 = (ArrayCreationExpr) arg;
         if (!nodeEquals(n.getElementType(), n2.getElementType()))
@@ -575,7 +546,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ArrayInitializerExpr n, final Visitable arg) {
         final ArrayInitializerExpr n2 = (ArrayInitializerExpr) arg;
         if (!nodesEquals(n.getValues(), n2.getValues()))
@@ -586,7 +556,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final AssignExpr n, final Visitable arg) {
         final AssignExpr n2 = (AssignExpr) arg;
         if (!objEquals(n.getOperator(), n2.getOperator()))
@@ -601,7 +570,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final BinaryExpr n, final Visitable arg) {
         final BinaryExpr n2 = (BinaryExpr) arg;
         if (!nodeEquals(n.getLeft(), n2.getLeft()))
@@ -616,7 +584,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final CastExpr n, final Visitable arg) {
         final CastExpr n2 = (CastExpr) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -629,7 +596,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ClassExpr n, final Visitable arg) {
         final ClassExpr n2 = (ClassExpr) arg;
         if (!nodeEquals(n.getType(), n2.getType()))
@@ -640,7 +606,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ConditionalExpr n, final Visitable arg) {
         final ConditionalExpr n2 = (ConditionalExpr) arg;
         if (!nodeEquals(n.getCondition(), n2.getCondition()))
@@ -655,7 +620,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final EnclosedExpr n, final Visitable arg) {
         final EnclosedExpr n2 = (EnclosedExpr) arg;
         if (!nodeEquals(n.getInner(), n2.getInner()))
@@ -666,7 +630,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final FieldAccessExpr n, final Visitable arg) {
         final FieldAccessExpr n2 = (FieldAccessExpr) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -681,7 +644,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final InstanceOfExpr n, final Visitable arg) {
         final InstanceOfExpr n2 = (InstanceOfExpr) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -694,7 +656,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final StringLiteralExpr n, final Visitable arg) {
         final StringLiteralExpr n2 = (StringLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -705,7 +666,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final IntegerLiteralExpr n, final Visitable arg) {
         final IntegerLiteralExpr n2 = (IntegerLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -716,7 +676,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final LongLiteralExpr n, final Visitable arg) {
         final LongLiteralExpr n2 = (LongLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -727,7 +686,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final CharLiteralExpr n, final Visitable arg) {
         final CharLiteralExpr n2 = (CharLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -738,7 +696,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final DoubleLiteralExpr n, final Visitable arg) {
         final DoubleLiteralExpr n2 = (DoubleLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -749,7 +706,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final BooleanLiteralExpr n, final Visitable arg) {
         final BooleanLiteralExpr n2 = (BooleanLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -760,7 +716,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final NullLiteralExpr n, final Visitable arg) {
         final NullLiteralExpr n2 = (NullLiteralExpr) arg;
         if (!nodeEquals(n.getComment(), n2.getComment()))
@@ -769,7 +724,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final MethodCallExpr n, final Visitable arg) {
         final MethodCallExpr n2 = (MethodCallExpr) arg;
         if (!nodesEquals(n.getArguments(), n2.getArguments()))
@@ -786,7 +740,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final NameExpr n, final Visitable arg) {
         final NameExpr n2 = (NameExpr) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -797,7 +750,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ObjectCreationExpr n, final Visitable arg) {
         final ObjectCreationExpr n2 = (ObjectCreationExpr) arg;
         if (!nodesEquals(n.getAnonymousClassBody(), n2.getAnonymousClassBody()))
@@ -816,11 +768,8 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final Name n, final Visitable arg) {
         final Name n2 = (Name) arg;
-        if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
-            return false;
         if (!objEquals(n.getIdentifier(), n2.getIdentifier()))
             return false;
         if (!nodeEquals(n.getQualifier(), n2.getQualifier()))
@@ -831,7 +780,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final SimpleName n, final Visitable arg) {
         final SimpleName n2 = (SimpleName) arg;
         if (!objEquals(n.getIdentifier(), n2.getIdentifier()))
@@ -842,10 +790,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ThisExpr n, final Visitable arg) {
         final ThisExpr n2 = (ThisExpr) arg;
-        if (!nodeEquals(n.getClassExpr(), n2.getClassExpr()))
+        if (!nodeEquals(n.getTypeName(), n2.getTypeName()))
             return false;
         if (!nodeEquals(n.getComment(), n2.getComment()))
             return false;
@@ -853,10 +800,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final SuperExpr n, final Visitable arg) {
         final SuperExpr n2 = (SuperExpr) arg;
-        if (!nodeEquals(n.getClassExpr(), n2.getClassExpr()))
+        if (!nodeEquals(n.getTypeName(), n2.getTypeName()))
             return false;
         if (!nodeEquals(n.getComment(), n2.getComment()))
             return false;
@@ -864,7 +810,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final UnaryExpr n, final Visitable arg) {
         final UnaryExpr n2 = (UnaryExpr) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -877,12 +822,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final VariableDeclarationExpr n, final Visitable arg) {
         final VariableDeclarationExpr n2 = (VariableDeclarationExpr) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodesEquals(n.getVariables(), n2.getVariables()))
             return false;
@@ -892,7 +836,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final MarkerAnnotationExpr n, final Visitable arg) {
         final MarkerAnnotationExpr n2 = (MarkerAnnotationExpr) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -903,7 +846,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final SingleMemberAnnotationExpr n, final Visitable arg) {
         final SingleMemberAnnotationExpr n2 = (SingleMemberAnnotationExpr) arg;
         if (!nodeEquals(n.getMemberValue(), n2.getMemberValue()))
@@ -916,7 +858,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final NormalAnnotationExpr n, final Visitable arg) {
         final NormalAnnotationExpr n2 = (NormalAnnotationExpr) arg;
         if (!nodesEquals(n.getPairs(), n2.getPairs()))
@@ -929,7 +870,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final MemberValuePair n, final Visitable arg) {
         final MemberValuePair n2 = (MemberValuePair) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -942,7 +882,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ExplicitConstructorInvocationStmt n, final Visitable arg) {
         final ExplicitConstructorInvocationStmt n2 = (ExplicitConstructorInvocationStmt) arg;
         if (!nodesEquals(n.getArguments(), n2.getArguments()))
@@ -959,7 +898,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final LocalClassDeclarationStmt n, final Visitable arg) {
         final LocalClassDeclarationStmt n2 = (LocalClassDeclarationStmt) arg;
         if (!nodeEquals(n.getClassDeclaration(), n2.getClassDeclaration()))
@@ -970,7 +908,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final AssertStmt n, final Visitable arg) {
         final AssertStmt n2 = (AssertStmt) arg;
         if (!nodeEquals(n.getCheck(), n2.getCheck()))
@@ -983,7 +920,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final BlockStmt n, final Visitable arg) {
         final BlockStmt n2 = (BlockStmt) arg;
         if (!nodesEquals(n.getStatements(), n2.getStatements()))
@@ -994,7 +930,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final LabeledStmt n, final Visitable arg) {
         final LabeledStmt n2 = (LabeledStmt) arg;
         if (!nodeEquals(n.getLabel(), n2.getLabel()))
@@ -1007,7 +942,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final EmptyStmt n, final Visitable arg) {
         final EmptyStmt n2 = (EmptyStmt) arg;
         if (!nodeEquals(n.getComment(), n2.getComment()))
@@ -1016,7 +950,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ExpressionStmt n, final Visitable arg) {
         final ExpressionStmt n2 = (ExpressionStmt) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -1027,7 +960,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final SwitchStmt n, final Visitable arg) {
         final SwitchStmt n2 = (SwitchStmt) arg;
         if (!nodesEquals(n.getEntries(), n2.getEntries()))
@@ -1040,23 +972,23 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
-    public Boolean visit(final SwitchEntryStmt n, final Visitable arg) {
-        final SwitchEntryStmt n2 = (SwitchEntryStmt) arg;
-        if (!nodeEquals(n.getLabel(), n2.getLabel()))
+    public Boolean visit(final SwitchEntry n, final Visitable arg) {
+        final SwitchEntry n2 = (SwitchEntry) arg;
+        if (!nodesEquals(n.getLabels(), n2.getLabels()))
             return false;
         if (!nodesEquals(n.getStatements(), n2.getStatements()))
             return false;
+        if (!objEquals(n.getType(), n2.getType()))
+            return false;
         if (!nodeEquals(n.getComment(), n2.getComment()))
             return false;
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final BreakStmt n, final Visitable arg) {
         final BreakStmt n2 = (BreakStmt) arg;
-        if (!nodeEquals(n.getLabel(), n2.getLabel()))
+        if (!nodeEquals(n.getValue(), n2.getValue()))
             return false;
         if (!nodeEquals(n.getComment(), n2.getComment()))
             return false;
@@ -1064,7 +996,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ReturnStmt n, final Visitable arg) {
         final ReturnStmt n2 = (ReturnStmt) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -1075,7 +1006,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final IfStmt n, final Visitable arg) {
         final IfStmt n2 = (IfStmt) arg;
         if (!nodeEquals(n.getCondition(), n2.getCondition()))
@@ -1090,7 +1020,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final WhileStmt n, final Visitable arg) {
         final WhileStmt n2 = (WhileStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1103,7 +1032,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ContinueStmt n, final Visitable arg) {
         final ContinueStmt n2 = (ContinueStmt) arg;
         if (!nodeEquals(n.getLabel(), n2.getLabel()))
@@ -1114,7 +1042,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final DoStmt n, final Visitable arg) {
         final DoStmt n2 = (DoStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1127,9 +1054,8 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
-    public Boolean visit(final ForeachStmt n, final Visitable arg) {
-        final ForeachStmt n2 = (ForeachStmt) arg;
+    public Boolean visit(final ForEachStmt n, final Visitable arg) {
+        final ForEachStmt n2 = (ForEachStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
             return false;
         if (!nodeEquals(n.getIterable(), n2.getIterable()))
@@ -1142,7 +1068,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ForStmt n, final Visitable arg) {
         final ForStmt n2 = (ForStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1159,7 +1084,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ThrowStmt n, final Visitable arg) {
         final ThrowStmt n2 = (ThrowStmt) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -1170,7 +1094,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final SynchronizedStmt n, final Visitable arg) {
         final SynchronizedStmt n2 = (SynchronizedStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1183,7 +1106,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final TryStmt n, final Visitable arg) {
         final TryStmt n2 = (TryStmt) arg;
         if (!nodesEquals(n.getCatchClauses(), n2.getCatchClauses()))
@@ -1200,7 +1122,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final CatchClause n, final Visitable arg) {
         final CatchClause n2 = (CatchClause) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1213,7 +1134,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final LambdaExpr n, final Visitable arg) {
         final LambdaExpr n2 = (LambdaExpr) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1228,7 +1148,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final MethodReferenceExpr n, final Visitable arg) {
         final MethodReferenceExpr n2 = (MethodReferenceExpr) arg;
         if (!objEquals(n.getIdentifier(), n2.getIdentifier()))
@@ -1243,7 +1162,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final TypeExpr n, final Visitable arg) {
         final TypeExpr n2 = (TypeExpr) arg;
         if (!nodeEquals(n.getType(), n2.getType()))
@@ -1254,7 +1172,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ImportDeclaration n, final Visitable arg) {
         final ImportDeclaration n2 = (ImportDeclaration) arg;
         if (!objEquals(n.isAsterisk(), n2.isAsterisk()))
@@ -1274,15 +1191,14 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ModuleDeclaration n, final Visitable arg) {
         final ModuleDeclaration n2 = (ModuleDeclaration) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
             return false;
+        if (!nodesEquals(n.getDirectives(), n2.getDirectives()))
+            return false;
         if (!objEquals(n.isOpen(), n2.isOpen()))
             return false;
-        if (!nodesEquals(n.getModuleStmts(), n2.getModuleStmts()))
-            return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
         if (!nodeEquals(n.getComment(), n2.getComment()))
@@ -1291,10 +1207,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
-    public Boolean visit(final ModuleRequiresStmt n, final Visitable arg) {
-        final ModuleRequiresStmt n2 = (ModuleRequiresStmt) arg;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+    public Boolean visit(final ModuleRequiresDirective n, final Visitable arg) {
+        final ModuleRequiresDirective n2 = (ModuleRequiresDirective) arg;
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -1304,9 +1219,8 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
-    public Boolean visit(final ModuleExportsStmt n, final Visitable arg) {
-        final ModuleExportsStmt n2 = (ModuleExportsStmt) arg;
+    public Boolean visit(final ModuleExportsDirective n, final Visitable arg) {
+        final ModuleExportsDirective n2 = (ModuleExportsDirective) arg;
         if (!nodesEquals(n.getModuleNames(), n2.getModuleNames()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -1317,12 +1231,11 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
-    public Boolean visit(final ModuleProvidesStmt n, final Visitable arg) {
-        final ModuleProvidesStmt n2 = (ModuleProvidesStmt) arg;
-        if (!nodeEquals(n.getType(), n2.getType()))
+    public Boolean visit(final ModuleProvidesDirective n, final Visitable arg) {
+        final ModuleProvidesDirective n2 = (ModuleProvidesDirective) arg;
+        if (!nodeEquals(n.getName(), n2.getName()))
             return false;
-        if (!nodesEquals(n.getWithTypes(), n2.getWithTypes()))
+        if (!nodesEquals(n.getWith(), n2.getWith()))
             return false;
         if (!nodeEquals(n.getComment(), n2.getComment()))
             return false;
@@ -1330,10 +1243,9 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
-    public Boolean visit(final ModuleUsesStmt n, final Visitable arg) {
-        final ModuleUsesStmt n2 = (ModuleUsesStmt) arg;
-        if (!nodeEquals(n.getType(), n2.getType()))
+    public Boolean visit(final ModuleUsesDirective n, final Visitable arg) {
+        final ModuleUsesDirective n2 = (ModuleUsesDirective) arg;
+        if (!nodeEquals(n.getName(), n2.getName()))
             return false;
         if (!nodeEquals(n.getComment(), n2.getComment()))
             return false;
@@ -1341,9 +1253,8 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
-    public Boolean visit(final ModuleOpensStmt n, final Visitable arg) {
-        final ModuleOpensStmt n2 = (ModuleOpensStmt) arg;
+    public Boolean visit(final ModuleOpensDirective n, final Visitable arg) {
+        final ModuleOpensDirective n2 = (ModuleOpensDirective) arg;
         if (!nodesEquals(n.getModuleNames(), n2.getModuleNames()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -1354,7 +1265,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final UnparsableStmt n, final Visitable arg) {
         final UnparsableStmt n2 = (UnparsableStmt) arg;
         if (!nodeEquals(n.getComment(), n2.getComment()))
@@ -1363,7 +1273,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.EqualsVisitorGenerator")
     public Boolean visit(final ReceiverParameter n, final Visitable arg) {
         final ReceiverParameter n2 = (ReceiverParameter) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -1386,4 +1295,26 @@
             return false;
         return true;
     }
+
+    @Override
+    public Boolean visit(final Modifier n, final Visitable arg) {
+        final Modifier n2 = (Modifier) arg;
+        if (!objEquals(n.getKeyword(), n2.getKeyword()))
+            return false;
+        if (!nodeEquals(n.getComment(), n2.getComment()))
+            return false;
+        return true;
+    }
+
+    @Override
+    public Boolean visit(final SwitchExpr n, final Visitable arg) {
+        final SwitchExpr n2 = (SwitchExpr) arg;
+        if (!nodesEquals(n.getEntries(), n2.getEntries()))
+            return false;
+        if (!nodeEquals(n.getSelector(), n2.getSelector()))
+            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 2defdfa..15e7d97 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -44,7 +43,6 @@
  */
 public abstract class GenericListVisitorAdapter<R, A> implements GenericVisitor<List<R>, A> {
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final AnnotationDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -54,6 +52,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -71,7 +74,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final AnnotationMemberDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -81,6 +83,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -103,7 +110,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ArrayAccessExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -125,7 +131,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ArrayCreationExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -152,7 +157,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ArrayCreationLevel n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -174,7 +178,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ArrayInitializerExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -191,7 +194,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ArrayType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -213,7 +215,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final AssertStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -235,7 +236,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final AssignExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -257,7 +257,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final BinaryExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -279,7 +278,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final BlockComment n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -291,7 +289,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final BlockStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -308,7 +305,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final BooleanLiteralExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -320,12 +316,11 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final BreakStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
-        if (n.getLabel().isPresent()) {
-            tmp = n.getLabel().get().accept(this, arg);
+        if (n.getValue().isPresent()) {
+            tmp = n.getValue().get().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
         }
@@ -337,7 +332,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final CastExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -359,7 +353,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final CatchClause n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -381,7 +374,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final CharLiteralExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -393,7 +385,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ClassExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -410,7 +401,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ClassOrInterfaceDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -435,6 +425,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -452,7 +447,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ClassOrInterfaceType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -484,7 +478,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final CompilationUnit n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -516,7 +509,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ConditionalExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -543,7 +535,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ConstructorDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -553,6 +544,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -590,7 +586,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ContinueStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -607,7 +602,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final DoStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -629,7 +623,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final DoubleLiteralExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -641,7 +634,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final EmptyStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -653,7 +645,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final EnclosedExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -670,7 +661,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final EnumConstantDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -702,7 +692,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final EnumDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -722,6 +711,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -739,7 +733,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ExplicitConstructorInvocationStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -766,7 +759,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ExpressionStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -783,7 +775,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final FieldAccessExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -810,11 +801,15 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final FieldDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getVariables().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -832,7 +827,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ForStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -864,8 +858,7 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
-    public List<R> visit(final ForeachStmt n, final A arg) {
+    public List<R> visit(final ForEachStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
         {
@@ -891,7 +884,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final IfStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -918,7 +910,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ImportDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -935,7 +926,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final InitializerDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -957,7 +947,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final InstanceOfExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -979,7 +968,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final IntegerLiteralExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -991,7 +979,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final IntersectionType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1013,7 +1000,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final JavadocComment n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1025,7 +1011,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final LabeledStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1047,7 +1032,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final LambdaExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1069,7 +1053,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final LineComment n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1081,7 +1064,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final LocalClassDeclarationStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1098,7 +1080,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final LongLiteralExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1110,7 +1091,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final MarkerAnnotationExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1127,7 +1107,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final MemberValuePair n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1149,7 +1128,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final MethodCallExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1181,7 +1159,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final MethodDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1196,6 +1173,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -1233,7 +1215,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final MethodReferenceExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1255,7 +1236,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final NameExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1272,15 +1252,9 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final Name 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.getQualifier().isPresent()) {
             tmp = n.getQualifier().get().accept(this, arg);
             if (tmp != null)
@@ -1294,7 +1268,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final NormalAnnotationExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1316,7 +1289,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final NullLiteralExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1328,7 +1300,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ObjectCreationExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1365,7 +1336,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final PackageDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1387,7 +1357,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final Parameter n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1397,6 +1366,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -1419,7 +1393,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final PrimitiveType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1436,7 +1409,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ReturnStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1453,7 +1425,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final SimpleName n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1465,7 +1436,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final SingleMemberAnnotationExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1487,7 +1457,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final StringLiteralExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1499,12 +1468,11 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final SuperExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
-        if (n.getClassExpr().isPresent()) {
-            tmp = n.getClassExpr().get().accept(this, arg);
+        if (n.getTypeName().isPresent()) {
+            tmp = n.getTypeName().get().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
         }
@@ -1516,12 +1484,11 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
-    public List<R> visit(final SwitchEntryStmt n, final A arg) {
+    public List<R> visit(final SwitchEntry n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
-        if (n.getLabel().isPresent()) {
-            tmp = n.getLabel().get().accept(this, arg);
+        {
+            tmp = n.getLabels().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
         }
@@ -1538,7 +1505,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final SwitchStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1560,7 +1526,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final SynchronizedStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1582,12 +1547,11 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ThisExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
-        if (n.getClassExpr().isPresent()) {
-            tmp = n.getClassExpr().get().accept(this, arg);
+        if (n.getTypeName().isPresent()) {
+            tmp = n.getTypeName().get().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
         }
@@ -1599,7 +1563,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ThrowStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1616,7 +1579,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final TryStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1648,7 +1610,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final TypeExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1665,7 +1626,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final TypeParameter n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1692,7 +1652,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final UnaryExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1709,7 +1668,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final UnionType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1731,7 +1689,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final UnknownType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1748,7 +1705,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final VariableDeclarationExpr n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1758,6 +1714,11 @@
                 result.addAll(tmp);
         }
         {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
             tmp = n.getVariables().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
@@ -1770,7 +1731,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final VariableDeclarator n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1797,7 +1757,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final VoidType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1814,7 +1773,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final WhileStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1836,7 +1794,6 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final WildcardType n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1869,7 +1826,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ModuleDeclaration n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -1879,7 +1835,7 @@
                 result.addAll(tmp);
         }
         {
-            tmp = n.getModuleStmts().accept(this, arg);
+            tmp = n.getDirectives().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
         }
@@ -1897,8 +1853,7 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
-    public List<R> visit(final ModuleExportsStmt n, final A arg) {
+    public List<R> visit(final ModuleExportsDirective n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
         {
@@ -1920,8 +1875,7 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
-    public List<R> visit(final ModuleOpensStmt n, final A arg) {
+    public List<R> visit(final ModuleOpensDirective n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
         {
@@ -1943,17 +1897,16 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
-    public List<R> visit(final ModuleProvidesStmt n, final A arg) {
+    public List<R> visit(final ModuleProvidesDirective n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
         {
-            tmp = n.getType().accept(this, arg);
+            tmp = n.getName().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
         }
         {
-            tmp = n.getWithTypes().accept(this, arg);
+            tmp = n.getWith().accept(this, arg);
             if (tmp != null)
                 result.addAll(tmp);
         }
@@ -1966,8 +1919,29 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
-    public List<R> visit(final ModuleRequiresStmt n, final A arg) {
+    public List<R> visit(final ModuleRequiresDirective n, final A arg) {
+        List<R> result = new ArrayList<>();
+        List<R> tmp;
+        {
+            tmp = n.getModifiers().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
+            tmp = n.getName().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;
+    }
+
+    @Override
+    public List<R> visit(final ModuleUsesDirective n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
         {
@@ -1984,25 +1958,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
-    public List<R> visit(final ModuleUsesStmt n, final A arg) {
-        List<R> result = new ArrayList<>();
-        List<R> tmp;
-        {
-            tmp = n.getType().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;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final UnparsableStmt n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -2015,7 +1970,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericListVisitorAdapterGenerator")
     public List<R> visit(final ReceiverParameter n, final A arg) {
         List<R> result = new ArrayList<>();
         List<R> tmp;
@@ -2058,4 +2012,38 @@
         }
         return result;
     }
+
+    @Override
+    public List<R> visit(final Modifier n, final A arg) {
+        List<R> result = new ArrayList<>();
+        List<R> tmp;
+        if (n.getComment().isPresent()) {
+            tmp = n.getComment().get().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        return result;
+    }
+
+    @Override
+    public List<R> visit(final SwitchExpr n, final A arg) {
+        List<R> result = new ArrayList<>();
+        List<R> tmp;
+        {
+            tmp = n.getEntries().accept(this, arg);
+            if (tmp != null)
+                result.addAll(tmp);
+        }
+        {
+            tmp = n.getSelector().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 494013c..744ff55 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that has a return value.
@@ -39,281 +38,195 @@
 public interface GenericVisitor<R, A> {
 
     // - Compilation Unit ----------------------------------
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(CompilationUnit n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(PackageDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(TypeParameter n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(LineComment n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(BlockComment n, A arg);
 
     // - Body ----------------------------------------------
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ClassOrInterfaceDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(EnumDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(EnumConstantDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(AnnotationDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(AnnotationMemberDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(FieldDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(VariableDeclarator n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ConstructorDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(MethodDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(Parameter n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(InitializerDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(JavadocComment n, A arg);
 
     // - Type ----------------------------------------------
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ClassOrInterfaceType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(PrimitiveType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ArrayType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ArrayCreationLevel n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(IntersectionType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(UnionType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(VoidType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(WildcardType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(UnknownType n, A arg);
 
     // - Expression ----------------------------------------
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ArrayAccessExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ArrayCreationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ArrayInitializerExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(AssignExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(BinaryExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(CastExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ClassExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ConditionalExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(EnclosedExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(FieldAccessExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(InstanceOfExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(StringLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(IntegerLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(LongLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(CharLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(DoubleLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(BooleanLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(NullLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(MethodCallExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(NameExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ObjectCreationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ThisExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(SuperExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(UnaryExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(VariableDeclarationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(MarkerAnnotationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(SingleMemberAnnotationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(NormalAnnotationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(MemberValuePair n, A arg);
 
     // - Statements ----------------------------------------
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ExplicitConstructorInvocationStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(LocalClassDeclarationStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(AssertStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(BlockStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(LabeledStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(EmptyStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ExpressionStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(SwitchStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
-    R visit(SwitchEntryStmt n, A arg);
+    R visit(SwitchEntry n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(BreakStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ReturnStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(IfStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(WhileStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ContinueStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(DoStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
-    R visit(ForeachStmt n, A arg);
+    R visit(ForEachStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ForStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ThrowStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(SynchronizedStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(TryStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(CatchClause n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(LambdaExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(MethodReferenceExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(TypeExpr n, A arg);
 
     R visit(NodeList n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(Name n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(SimpleName n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ImportDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ModuleDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
-    R visit(ModuleRequiresStmt n, A arg);
+    R visit(ModuleRequiresDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
-    R visit(ModuleExportsStmt n, A arg);
+    R visit(ModuleExportsDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
-    R visit(ModuleProvidesStmt n, A arg);
+    R visit(ModuleProvidesDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
-    R visit(ModuleUsesStmt n, A arg);
+    R visit(ModuleUsesDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
-    R visit(ModuleOpensStmt n, A arg);
+    R visit(ModuleOpensDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(UnparsableStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorGenerator")
     R visit(ReceiverParameter n, A arg);
 
     R visit(VarType n, A arg);
+
+    R visit(Modifier n, A arg);
+
+    R visit(SwitchExpr 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 3d5de4f..529100c 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that has a return value (R), and has a default implementation for all its visit
@@ -41,7 +40,6 @@
 public abstract class GenericVisitorAdapter<R, A> implements GenericVisitor<R, A> {
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final AnnotationDeclaration n, final A arg) {
         R result;
         {
@@ -50,6 +48,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -68,7 +71,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final AnnotationMemberDeclaration n, final A arg) {
         R result;
         if (n.getDefaultValue().isPresent()) {
@@ -77,6 +79,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -100,7 +107,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ArrayAccessExpr n, final A arg) {
         R result;
         {
@@ -122,7 +128,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ArrayCreationExpr n, final A arg) {
         R result;
         {
@@ -149,7 +154,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ArrayInitializerExpr n, final A arg) {
         R result;
         {
@@ -166,7 +170,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final AssertStmt n, final A arg) {
         R result;
         {
@@ -188,7 +191,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final AssignExpr n, final A arg) {
         R result;
         {
@@ -210,7 +212,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final BinaryExpr n, final A arg) {
         R result;
         {
@@ -232,7 +233,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final BlockStmt n, final A arg) {
         R result;
         {
@@ -249,7 +249,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final BooleanLiteralExpr n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -261,11 +260,10 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final BreakStmt n, final A arg) {
         R result;
-        if (n.getLabel().isPresent()) {
-            result = n.getLabel().get().accept(this, arg);
+        if (n.getValue().isPresent()) {
+            result = n.getValue().get().accept(this, arg);
             if (result != null)
                 return result;
         }
@@ -278,7 +276,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final CastExpr n, final A arg) {
         R result;
         {
@@ -300,7 +297,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final CatchClause n, final A arg) {
         R result;
         {
@@ -322,7 +318,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final CharLiteralExpr n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -334,7 +329,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ClassExpr n, final A arg) {
         R result;
         {
@@ -351,7 +345,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ClassOrInterfaceDeclaration n, final A arg) {
         R result;
         {
@@ -375,6 +368,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -393,7 +391,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ClassOrInterfaceType n, final A arg) {
         R result;
         {
@@ -425,7 +422,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final CompilationUnit n, final A arg) {
         R result;
         {
@@ -457,7 +453,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ConditionalExpr n, final A arg) {
         R result;
         {
@@ -484,7 +479,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ConstructorDeclaration n, final A arg) {
         R result;
         {
@@ -493,6 +487,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -531,7 +530,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ContinueStmt n, final A arg) {
         R result;
         if (n.getLabel().isPresent()) {
@@ -548,7 +546,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final DoStmt n, final A arg) {
         R result;
         {
@@ -570,7 +567,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final DoubleLiteralExpr n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -582,7 +578,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final EmptyStmt n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -594,7 +589,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final EnclosedExpr n, final A arg) {
         R result;
         {
@@ -611,7 +605,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final EnumConstantDeclaration n, final A arg) {
         R result;
         {
@@ -643,7 +636,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final EnumDeclaration n, final A arg) {
         R result;
         {
@@ -662,6 +654,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -680,7 +677,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ExplicitConstructorInvocationStmt n, final A arg) {
         R result;
         {
@@ -707,7 +703,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ExpressionStmt n, final A arg) {
         R result;
         {
@@ -724,7 +719,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final FieldAccessExpr n, final A arg) {
         R result;
         {
@@ -751,10 +745,14 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final FieldDeclaration n, final A arg) {
         R result;
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getVariables().accept(this, arg);
             if (result != null)
                 return result;
@@ -773,8 +771,7 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
-    public R visit(final ForeachStmt n, final A arg) {
+    public R visit(final ForEachStmt n, final A arg) {
         R result;
         {
             result = n.getBody().accept(this, arg);
@@ -800,7 +797,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ForStmt n, final A arg) {
         R result;
         {
@@ -832,7 +828,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final IfStmt n, final A arg) {
         R result;
         {
@@ -859,7 +854,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final InitializerDeclaration n, final A arg) {
         R result;
         {
@@ -881,7 +875,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final InstanceOfExpr n, final A arg) {
         R result;
         {
@@ -903,7 +896,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final IntegerLiteralExpr n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -915,7 +907,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final JavadocComment n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -927,7 +918,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final LabeledStmt n, final A arg) {
         R result;
         {
@@ -949,7 +939,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final LongLiteralExpr n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -961,7 +950,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final MarkerAnnotationExpr n, final A arg) {
         R result;
         {
@@ -978,7 +966,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final MemberValuePair n, final A arg) {
         R result;
         {
@@ -1000,7 +987,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final MethodCallExpr n, final A arg) {
         R result;
         {
@@ -1032,7 +1018,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final MethodDeclaration n, final A arg) {
         R result;
         if (n.getBody().isPresent()) {
@@ -1046,6 +1031,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -1084,7 +1074,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final NameExpr n, final A arg) {
         R result;
         {
@@ -1101,7 +1090,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final NormalAnnotationExpr n, final A arg) {
         R result;
         {
@@ -1123,7 +1111,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final NullLiteralExpr n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -1135,7 +1122,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ObjectCreationExpr n, final A arg) {
         R result;
         if (n.getAnonymousClassBody().isPresent()) {
@@ -1172,7 +1158,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final PackageDeclaration n, final A arg) {
         R result;
         {
@@ -1194,7 +1179,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final Parameter n, final A arg) {
         R result;
         {
@@ -1203,6 +1187,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -1226,7 +1215,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final PrimitiveType n, final A arg) {
         R result;
         {
@@ -1243,14 +1231,8 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final Name n, final A arg) {
         R result;
-        {
-            result = n.getAnnotations().accept(this, arg);
-            if (result != null)
-                return result;
-        }
         if (n.getQualifier().isPresent()) {
             result = n.getQualifier().get().accept(this, arg);
             if (result != null)
@@ -1265,7 +1247,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final SimpleName n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -1277,7 +1258,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ArrayType n, final A arg) {
         R result;
         {
@@ -1299,7 +1279,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ArrayCreationLevel n, final A arg) {
         R result;
         {
@@ -1321,7 +1300,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final IntersectionType n, final A arg) {
         R result;
         {
@@ -1343,7 +1321,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final UnionType n, final A arg) {
         R result;
         {
@@ -1365,7 +1342,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ReturnStmt n, final A arg) {
         R result;
         if (n.getExpression().isPresent()) {
@@ -1382,7 +1358,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final SingleMemberAnnotationExpr n, final A arg) {
         R result;
         {
@@ -1404,7 +1379,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final StringLiteralExpr n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -1416,11 +1390,10 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final SuperExpr n, final A arg) {
         R result;
-        if (n.getClassExpr().isPresent()) {
-            result = n.getClassExpr().get().accept(this, arg);
+        if (n.getTypeName().isPresent()) {
+            result = n.getTypeName().get().accept(this, arg);
             if (result != null)
                 return result;
         }
@@ -1433,11 +1406,10 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
-    public R visit(final SwitchEntryStmt n, final A arg) {
+    public R visit(final SwitchEntry n, final A arg) {
         R result;
-        if (n.getLabel().isPresent()) {
-            result = n.getLabel().get().accept(this, arg);
+        {
+            result = n.getLabels().accept(this, arg);
             if (result != null)
                 return result;
         }
@@ -1455,7 +1427,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final SwitchStmt n, final A arg) {
         R result;
         {
@@ -1477,7 +1448,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final SynchronizedStmt n, final A arg) {
         R result;
         {
@@ -1499,11 +1469,10 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ThisExpr n, final A arg) {
         R result;
-        if (n.getClassExpr().isPresent()) {
-            result = n.getClassExpr().get().accept(this, arg);
+        if (n.getTypeName().isPresent()) {
+            result = n.getTypeName().get().accept(this, arg);
             if (result != null)
                 return result;
         }
@@ -1516,7 +1485,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ThrowStmt n, final A arg) {
         R result;
         {
@@ -1533,7 +1501,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final TryStmt n, final A arg) {
         R result;
         {
@@ -1565,7 +1532,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final LocalClassDeclarationStmt n, final A arg) {
         R result;
         {
@@ -1582,7 +1548,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final TypeParameter n, final A arg) {
         R result;
         {
@@ -1609,7 +1574,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final UnaryExpr n, final A arg) {
         R result;
         {
@@ -1626,7 +1590,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final UnknownType n, final A arg) {
         R result;
         {
@@ -1643,7 +1606,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final VariableDeclarationExpr n, final A arg) {
         R result;
         {
@@ -1652,6 +1614,11 @@
                 return result;
         }
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getVariables().accept(this, arg);
             if (result != null)
                 return result;
@@ -1665,7 +1632,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final VariableDeclarator n, final A arg) {
         R result;
         if (n.getInitializer().isPresent()) {
@@ -1692,7 +1658,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final VoidType n, final A arg) {
         R result;
         {
@@ -1709,7 +1674,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final WhileStmt n, final A arg) {
         R result;
         {
@@ -1731,7 +1695,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final WildcardType n, final A arg) {
         R result;
         if (n.getExtendedType().isPresent()) {
@@ -1758,7 +1721,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final LambdaExpr n, final A arg) {
         R result;
         {
@@ -1780,7 +1742,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final MethodReferenceExpr n, final A arg) {
         R result;
         {
@@ -1802,7 +1763,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final TypeExpr n, final A arg) {
         R result;
         {
@@ -1819,7 +1779,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ImportDeclaration n, final A arg) {
         R result;
         {
@@ -1836,7 +1795,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final BlockComment n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -1848,7 +1806,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final LineComment n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -1871,7 +1828,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ModuleDeclaration n, final A arg) {
         R result;
         {
@@ -1880,7 +1836,7 @@
                 return result;
         }
         {
-            result = n.getModuleStmts().accept(this, arg);
+            result = n.getDirectives().accept(this, arg);
             if (result != null)
                 return result;
         }
@@ -1898,10 +1854,14 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
-    public R visit(final ModuleRequiresStmt n, final A arg) {
+    public R visit(final ModuleRequiresDirective n, final A arg) {
         R result;
         {
+            result = n.getModifiers().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
             result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
@@ -1915,8 +1875,7 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
-    public R visit(final ModuleExportsStmt n, final A arg) {
+    public R visit(final ModuleExportsDirective n, final A arg) {
         R result;
         {
             result = n.getModuleNames().accept(this, arg);
@@ -1937,16 +1896,15 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
-    public R visit(final ModuleProvidesStmt n, final A arg) {
+    public R visit(final ModuleProvidesDirective n, final A arg) {
         R result;
         {
-            result = n.getType().accept(this, arg);
+            result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
         }
         {
-            result = n.getWithTypes().accept(this, arg);
+            result = n.getWith().accept(this, arg);
             if (result != null)
                 return result;
         }
@@ -1959,11 +1917,10 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
-    public R visit(final ModuleUsesStmt n, final A arg) {
+    public R visit(final ModuleUsesDirective n, final A arg) {
         R result;
         {
-            result = n.getType().accept(this, arg);
+            result = n.getName().accept(this, arg);
             if (result != null)
                 return result;
         }
@@ -1976,8 +1933,7 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
-    public R visit(final ModuleOpensStmt n, final A arg) {
+    public R visit(final ModuleOpensDirective n, final A arg) {
         R result;
         {
             result = n.getModuleNames().accept(this, arg);
@@ -1998,7 +1954,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final UnparsableStmt n, final A arg) {
         R result;
         if (n.getComment().isPresent()) {
@@ -2010,7 +1965,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorAdapterGenerator")
     public R visit(final ReceiverParameter n, final A arg) {
         R result;
         {
@@ -2051,4 +2005,36 @@
         }
         return null;
     }
+
+    @Override
+    public R visit(final Modifier n, final A arg) {
+        R result;
+        if (n.getComment().isPresent()) {
+            result = n.getComment().get().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        return null;
+    }
+
+    @Override
+    public R visit(final SwitchExpr n, final A arg) {
+        R result;
+        {
+            result = n.getEntries().accept(this, arg);
+            if (result != null)
+                return result;
+        }
+        {
+            result = n.getSelector().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 2cd9a0f..043a1a6 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that has a return value (R), and has default methods that are used when a specific visit method is not
@@ -52,493 +51,411 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final AnnotationDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final AnnotationMemberDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ArrayAccessExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ArrayCreationExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ArrayInitializerExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final AssertStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final AssignExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final BinaryExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final BlockStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final BooleanLiteralExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final BreakStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final CastExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final CatchClause n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final CharLiteralExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ClassExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ClassOrInterfaceDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ClassOrInterfaceType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final CompilationUnit n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ConditionalExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ConstructorDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ContinueStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final DoStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final DoubleLiteralExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final EmptyStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final EnclosedExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final EnumConstantDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final EnumDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ExplicitConstructorInvocationStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ExpressionStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final FieldAccessExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final FieldDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
-    public R visit(final ForeachStmt n, final A arg) {
+    public R visit(final ForEachStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ForStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final IfStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final InitializerDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final InstanceOfExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final IntegerLiteralExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final JavadocComment n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final LabeledStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final LongLiteralExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final MarkerAnnotationExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final MemberValuePair n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final MethodCallExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final MethodDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final NameExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final NormalAnnotationExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final NullLiteralExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ObjectCreationExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final PackageDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final Parameter n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final PrimitiveType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final Name n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final SimpleName n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ArrayType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ArrayCreationLevel n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final IntersectionType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final UnionType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ReturnStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final SingleMemberAnnotationExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final StringLiteralExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final SuperExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
-    public R visit(final SwitchEntryStmt n, final A arg) {
+    public R visit(final SwitchEntry n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final SwitchStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final SynchronizedStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ThisExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ThrowStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final TryStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final LocalClassDeclarationStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final TypeParameter n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final UnaryExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final UnknownType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final VariableDeclarationExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final VariableDeclarator n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final VoidType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final WhileStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final WildcardType n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final LambdaExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final MethodReferenceExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final TypeExpr n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ImportDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final BlockComment n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final LineComment n, final A arg) {
         return defaultAction(n, arg);
     }
@@ -549,49 +466,41 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ModuleDeclaration n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
-    public R visit(final ModuleRequiresStmt n, final A arg) {
+    public R visit(final ModuleRequiresDirective n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
-    public R visit(final ModuleExportsStmt n, final A arg) {
+    public R visit(final ModuleExportsDirective n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
-    public R visit(final ModuleProvidesStmt n, final A arg) {
+    public R visit(final ModuleProvidesDirective n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
-    public R visit(final ModuleUsesStmt n, final A arg) {
+    public R visit(final ModuleUsesDirective n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
-    public R visit(final ModuleOpensStmt n, final A arg) {
+    public R visit(final ModuleOpensDirective n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final UnparsableStmt n, final A arg) {
         return defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.GenericVisitorWithDefaultsGenerator")
     public R visit(final ReceiverParameter n, final A arg) {
         return defaultAction(n, arg);
     }
@@ -600,4 +509,14 @@
     public R visit(final VarType n, final A arg) {
         return defaultAction(n, arg);
     }
+
+    @Override
+    public R visit(final Modifier n, final A arg) {
+        return defaultAction(n, arg);
+    }
+
+    @Override
+    public R visit(final SwitchExpr 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 92da13e..d1f258a 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that calculates a deep hash code for a node by using the hash codes of all its properties,
@@ -47,279 +46,224 @@
         return node.accept(SINGLETON, null);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final AnnotationDeclaration n, final Void arg) {
-        return (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final AnnotationMemberDeclaration n, final Void arg) {
-        return (n.getDefaultValue().isPresent() ? n.getDefaultValue().get().accept(this, arg) : 0) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getDefaultValue().isPresent() ? n.getDefaultValue().get().accept(this, arg) : 0) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ArrayAccessExpr n, final Void arg) {
         return (n.getIndex().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ArrayCreationExpr n, final Void arg) {
         return (n.getElementType().accept(this, arg)) * 31 + (n.getInitializer().isPresent() ? n.getInitializer().get().accept(this, arg) : 0) * 31 + (n.getLevels().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ArrayCreationLevel n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getDimension().isPresent() ? n.getDimension().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ArrayInitializerExpr n, final Void arg) {
         return (n.getValues().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ArrayType n, final Void arg) {
         return (n.getComponentType().accept(this, arg)) * 31 + (n.getOrigin().hashCode()) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final AssertStmt n, final Void arg) {
         return (n.getCheck().accept(this, arg)) * 31 + (n.getMessage().isPresent() ? n.getMessage().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final AssignExpr n, final Void arg) {
         return (n.getOperator().hashCode()) * 31 + (n.getTarget().accept(this, arg)) * 31 + (n.getValue().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final BinaryExpr n, final Void arg) {
         return (n.getLeft().accept(this, arg)) * 31 + (n.getOperator().hashCode()) * 31 + (n.getRight().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final BlockComment n, final Void arg) {
         return (n.getContent().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final BlockStmt n, final Void arg) {
         return (n.getStatements().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final BooleanLiteralExpr n, final Void arg) {
         return (n.getValue() ? 1 : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final BreakStmt n, final Void arg) {
-        return (n.getLabel().isPresent() ? n.getLabel().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getValue().isPresent() ? n.getValue().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final CastExpr n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final CatchClause n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getParameter().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final CharLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ClassExpr n, final Void arg) {
         return (n.getType().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ClassOrInterfaceDeclaration n, final Void arg) {
-        return (n.getExtendedTypes().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.isInterface() ? 1 : 0) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getExtendedTypes().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.isInterface() ? 1 : 0) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ClassOrInterfaceType n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getScope().isPresent() ? n.getScope().get().accept(this, arg) : 0) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final CompilationUnit n, final Void arg) {
         return (n.getImports().accept(this, arg)) * 31 + (n.getModule().isPresent() ? n.getModule().get().accept(this, arg) : 0) * 31 + (n.getPackageDeclaration().isPresent() ? n.getPackageDeclaration().get().accept(this, arg) : 0) * 31 + (n.getTypes().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ConditionalExpr n, final Void arg) {
         return (n.getCondition().accept(this, arg)) * 31 + (n.getElseExpr().accept(this, arg)) * 31 + (n.getThenExpr().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ConstructorDeclaration n, final Void arg) {
-        return (n.getBody().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getBody().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ContinueStmt n, final Void arg) {
         return (n.getLabel().isPresent() ? n.getLabel().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final DoStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getCondition().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final DoubleLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final EmptyStmt n, final Void arg) {
         return (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final EnclosedExpr n, final Void arg) {
         return (n.getInner().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final EnumConstantDeclaration n, final Void arg) {
         return (n.getArguments().accept(this, arg)) * 31 + (n.getClassBody().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final EnumDeclaration n, final Void arg) {
-        return (n.getEntries().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getEntries().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ExplicitConstructorInvocationStmt n, final Void arg) {
         return (n.getArguments().accept(this, arg)) * 31 + (n.getExpression().isPresent() ? n.getExpression().get().accept(this, arg) : 0) * 31 + (n.isThis() ? 1 : 0) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ExpressionStmt n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final FieldAccessExpr n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getScope().accept(this, arg)) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final FieldDeclaration n, final Void arg) {
-        return (n.getModifiers().hashCode()) * 31 + (n.getVariables().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getModifiers().accept(this, arg)) * 31 + (n.getVariables().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ForStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getCompare().isPresent() ? n.getCompare().get().accept(this, arg) : 0) * 31 + (n.getInitialization().accept(this, arg)) * 31 + (n.getUpdate().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
-    public Integer visit(final ForeachStmt n, final Void arg) {
+    public Integer visit(final ForEachStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getIterable().accept(this, arg)) * 31 + (n.getVariable().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final IfStmt n, final Void arg) {
         return (n.getCondition().accept(this, arg)) * 31 + (n.getElseStmt().isPresent() ? n.getElseStmt().get().accept(this, arg) : 0) * 31 + (n.getThenStmt().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ImportDeclaration n, final Void arg) {
         return (n.isAsterisk() ? 1 : 0) * 31 + (n.isStatic() ? 1 : 0) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final InitializerDeclaration n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.isStatic() ? 1 : 0) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final InstanceOfExpr n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final IntegerLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final IntersectionType n, final Void arg) {
         return (n.getElements().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final JavadocComment n, final Void arg) {
         return (n.getContent().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final LabeledStmt n, final Void arg) {
         return (n.getLabel().accept(this, arg)) * 31 + (n.getStatement().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final LambdaExpr n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.isEnclosingParameters() ? 1 : 0) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final LineComment n, final Void arg) {
         return (n.getContent().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final LocalClassDeclarationStmt n, final Void arg) {
         return (n.getClassDeclaration().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final LongLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final MarkerAnnotationExpr n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final MemberValuePair n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getValue().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final MethodCallExpr n, final Void arg) {
         return (n.getArguments().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getScope().isPresent() ? n.getScope().get().accept(this, arg) : 0) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final MethodDeclaration n, final Void arg) {
-        return (n.getBody().isPresent() ? n.getBody().get().accept(this, arg) : 0) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getBody().isPresent() ? n.getBody().get().accept(this, arg) : 0) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final MethodReferenceExpr n, final Void arg) {
         return (n.getIdentifier().hashCode()) * 31 + (n.getScope().accept(this, arg)) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final NameExpr n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final Name n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getIdentifier().hashCode()) * 31 + (n.getQualifier().isPresent() ? n.getQualifier().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getIdentifier().hashCode()) * 31 + (n.getQualifier().isPresent() ? n.getQualifier().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
     public Integer visit(NodeList n, Void arg) {
@@ -330,183 +274,148 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final NormalAnnotationExpr n, final Void arg) {
         return (n.getPairs().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final NullLiteralExpr n, final Void arg) {
         return (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ObjectCreationExpr n, final Void arg) {
         return (n.getAnonymousClassBody().isPresent() ? n.getAnonymousClassBody().get().accept(this, arg) : 0) * 31 + (n.getArguments().accept(this, arg)) * 31 + (n.getScope().isPresent() ? n.getScope().get().accept(this, arg) : 0) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final PackageDeclaration n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final Parameter n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.isVarArgs() ? 1 : 0) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getVarArgsAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getAnnotations().accept(this, arg)) * 31 + (n.isVarArgs() ? 1 : 0) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getVarArgsAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final PrimitiveType n, final Void arg) {
         return (n.getType().hashCode()) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ReturnStmt n, final Void arg) {
         return (n.getExpression().isPresent() ? n.getExpression().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final SimpleName n, final Void arg) {
         return (n.getIdentifier().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final SingleMemberAnnotationExpr n, final Void arg) {
         return (n.getMemberValue().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final StringLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final SuperExpr n, final Void arg) {
-        return (n.getClassExpr().isPresent() ? n.getClassExpr().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getTypeName().isPresent() ? n.getTypeName().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
-    public Integer visit(final SwitchEntryStmt n, final Void arg) {
-        return (n.getLabel().isPresent() ? n.getLabel().get().accept(this, arg) : 0) * 31 + (n.getStatements().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+    public Integer visit(final SwitchEntry n, final Void arg) {
+        return (n.getLabels().accept(this, arg)) * 31 + (n.getStatements().accept(this, arg)) * 31 + (n.getType().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final SwitchStmt n, final Void arg) {
         return (n.getEntries().accept(this, arg)) * 31 + (n.getSelector().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final SynchronizedStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getExpression().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ThisExpr n, final Void arg) {
-        return (n.getClassExpr().isPresent() ? n.getClassExpr().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getTypeName().isPresent() ? n.getTypeName().get().accept(this, arg) : 0) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ThrowStmt n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final TryStmt n, final Void arg) {
         return (n.getCatchClauses().accept(this, arg)) * 31 + (n.getFinallyBlock().isPresent() ? n.getFinallyBlock().get().accept(this, arg) : 0) * 31 + (n.getResources().accept(this, arg)) * 31 + (n.getTryBlock().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final TypeExpr n, final Void arg) {
         return (n.getType().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final TypeParameter n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getTypeBound().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final UnaryExpr n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getOperator().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final UnionType n, final Void arg) {
         return (n.getElements().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final UnknownType n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final VariableDeclarationExpr n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getVariables().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getVariables().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final VariableDeclarator n, final Void arg) {
         return (n.getInitializer().isPresent() ? n.getInitializer().get().accept(this, arg) : 0) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final VoidType n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final WhileStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getCondition().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final WildcardType n, final Void arg) {
         return (n.getExtendedType().isPresent() ? n.getExtendedType().get().accept(this, arg) : 0) * 31 + (n.getSuperType().isPresent() ? n.getSuperType().get().accept(this, arg) : 0) * 31 + (n.getAnnotations().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final ModuleDeclaration n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.isOpen() ? 1 : 0) * 31 + (n.getModuleStmts().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getDirectives().accept(this, arg)) * 31 + (n.isOpen() ? 1 : 0) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
-    public Integer visit(final ModuleRequiresStmt n, final Void arg) {
-        return (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+    public Integer visit(final ModuleRequiresDirective n, final Void arg) {
+        return (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
-    public Integer visit(final ModuleExportsStmt n, final Void arg) {
+    public Integer visit(final ModuleExportsDirective n, final Void arg) {
         return (n.getModuleNames().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
-    public Integer visit(final ModuleProvidesStmt n, final Void arg) {
-        return (n.getType().accept(this, arg)) * 31 + (n.getWithTypes().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+    public Integer visit(final ModuleProvidesDirective n, final Void arg) {
+        return (n.getName().accept(this, arg)) * 31 + (n.getWith().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
-    public Integer visit(final ModuleUsesStmt n, final Void arg) {
-        return (n.getType().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+    public Integer visit(final ModuleUsesDirective n, final Void arg) {
+        return (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
-    public Integer visit(final ModuleOpensStmt n, final Void arg) {
+    public Integer visit(final ModuleOpensDirective n, final Void arg) {
         return (n.getModuleNames().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     public Integer visit(final UnparsableStmt n, final Void arg) {
         return (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.HashCodeVisitorGenerator")
     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);
     }
@@ -515,4 +424,14 @@
     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);
     }
+
+    @Override
+    public Integer visit(final Modifier n, final Void arg) {
+        return (n.getKeyword().hashCode()) * 31 + (n.getComment().isPresent() ? n.getComment().get().accept(this, arg) : 0);
+    }
+
+    @Override
+    public Integer visit(final SwitchExpr n, final Void arg) {
+        return (n.getEntries().accept(this, arg)) * 31 + (n.getSelector().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 c780864..ad7e0ae 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
@@ -31,17 +31,18 @@
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
 import com.github.javaparser.utils.Pair;
-import javax.annotation.Generated;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
+import static com.github.javaparser.utils.Utils.removeElementByObjectIdentity;
+import static com.github.javaparser.utils.Utils.replaceElementByObjectIdentity;
 
 /**
  * This visitor can be used to save time when some specific nodes needs
  * to be changed. To do that just extend this class and override the methods
  * from the nodes who needs to be changed, returning the changed node.
  * Returning null will remove the node.
- *
+ * <p>
  * If a node is removed that was required in its parent node,
  * the parent node will be removed too.
  *
@@ -50,15 +51,16 @@
 public class ModifierVisitor<A> implements GenericVisitor<Visitable, A> {
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final AnnotationDeclaration n, final A arg) {
         NodeList<BodyDeclaration<?>> members = modifyList(n.getMembers(), arg);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         if (name == null)
             return null;
         n.setMembers(members);
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setAnnotations(annotations);
         n.setComment(comment);
@@ -66,9 +68,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final AnnotationMemberDeclaration n, final A arg) {
         Expression defaultValue = n.getDefaultValue().map(s -> (Expression) s.accept(this, arg)).orElse(null);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         Type type = (Type) n.getType().accept(this, arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
@@ -76,6 +78,7 @@
         if (name == null || type == null)
             return null;
         n.setDefaultValue(defaultValue);
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setType(type);
         n.setAnnotations(annotations);
@@ -84,7 +87,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ArrayAccessExpr n, final A arg) {
         Expression index = (Expression) n.getIndex().accept(this, arg);
         Expression name = (Expression) n.getName().accept(this, arg);
@@ -98,7 +100,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ArrayCreationExpr n, final A arg) {
         Type elementType = (Type) n.getElementType().accept(this, arg);
         ArrayInitializerExpr initializer = n.getInitializer().map(s -> (ArrayInitializerExpr) s.accept(this, arg)).orElse(null);
@@ -114,7 +115,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ArrayInitializerExpr n, final A arg) {
         NodeList<Expression> values = modifyList(n.getValues(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -124,7 +124,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final AssertStmt n, final A arg) {
         Expression check = (Expression) n.getCheck().accept(this, arg);
         Expression message = n.getMessage().map(s -> (Expression) s.accept(this, arg)).orElse(null);
@@ -138,7 +137,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final AssignExpr n, final A arg) {
         Expression target = (Expression) n.getTarget().accept(this, arg);
         Expression value = (Expression) n.getValue().accept(this, arg);
@@ -152,7 +150,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final BinaryExpr n, final A arg) {
         Expression left = (Expression) n.getLeft().accept(this, arg);
         Expression right = (Expression) n.getRight().accept(this, arg);
@@ -168,7 +165,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final BlockStmt n, final A arg) {
         NodeList<Statement> statements = modifyList(n.getStatements(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -178,7 +174,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final BooleanLiteralExpr n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -186,17 +181,15 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final BreakStmt n, final A arg) {
-        SimpleName label = n.getLabel().map(s -> (SimpleName) s.accept(this, arg)).orElse(null);
+        Expression value = n.getValue().map(s -> (Expression) s.accept(this, arg)).orElse(null);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
-        n.setLabel(label);
+        n.setValue(value);
         n.setComment(comment);
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final CastExpr n, final A arg) {
         Expression expression = (Expression) n.getExpression().accept(this, arg);
         Type type = (Type) n.getType().accept(this, arg);
@@ -210,7 +203,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final CatchClause n, final A arg) {
         BlockStmt body = (BlockStmt) n.getBody().accept(this, arg);
         Parameter parameter = (Parameter) n.getParameter().accept(this, arg);
@@ -224,7 +216,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final CharLiteralExpr n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -232,7 +223,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ClassExpr n, final A arg) {
         Type type = (Type) n.getType().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -244,12 +234,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ClassOrInterfaceDeclaration n, final A arg) {
         NodeList<ClassOrInterfaceType> extendedTypes = modifyList(n.getExtendedTypes(), arg);
         NodeList<ClassOrInterfaceType> implementedTypes = modifyList(n.getImplementedTypes(), arg);
         NodeList<TypeParameter> typeParameters = modifyList(n.getTypeParameters(), arg);
         NodeList<BodyDeclaration<?>> members = modifyList(n.getMembers(), arg);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -259,6 +249,7 @@
         n.setImplementedTypes(implementedTypes);
         n.setTypeParameters(typeParameters);
         n.setMembers(members);
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setAnnotations(annotations);
         n.setComment(comment);
@@ -266,7 +257,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ClassOrInterfaceType n, final A arg) {
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         ClassOrInterfaceType scope = n.getScope().map(s -> (ClassOrInterfaceType) s.accept(this, arg)).orElse(null);
@@ -284,7 +274,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final CompilationUnit n, final A arg) {
         NodeList<ImportDeclaration> imports = modifyList(n.getImports(), arg);
         ModuleDeclaration module = n.getModule().map(s -> (ModuleDeclaration) s.accept(this, arg)).orElse(null);
@@ -300,7 +289,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ConditionalExpr n, final A arg) {
         Expression condition = (Expression) n.getCondition().accept(this, arg);
         Expression elseExpr = (Expression) n.getElseExpr().accept(this, arg);
@@ -316,9 +304,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ConstructorDeclaration n, final A arg) {
         BlockStmt body = (BlockStmt) n.getBody().accept(this, arg);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         NodeList<Parameter> parameters = modifyList(n.getParameters(), arg);
         ReceiverParameter receiverParameter = n.getReceiverParameter().map(s -> (ReceiverParameter) s.accept(this, arg)).orElse(null);
@@ -329,6 +317,7 @@
         if (body == null || name == null)
             return null;
         n.setBody(body);
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setParameters(parameters);
         n.setReceiverParameter(receiverParameter);
@@ -340,7 +329,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ContinueStmt n, final A arg) {
         SimpleName label = n.getLabel().map(s -> (SimpleName) s.accept(this, arg)).orElse(null);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -350,7 +338,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final DoStmt n, final A arg) {
         Statement body = (Statement) n.getBody().accept(this, arg);
         Expression condition = (Expression) n.getCondition().accept(this, arg);
@@ -364,7 +351,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final DoubleLiteralExpr n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -372,7 +358,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final EmptyStmt n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -380,7 +365,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final EnclosedExpr n, final A arg) {
         Expression inner = (Expression) n.getInner().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -392,7 +376,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final EnumConstantDeclaration n, final A arg) {
         NodeList<Expression> arguments = modifyList(n.getArguments(), arg);
         NodeList<BodyDeclaration<?>> classBody = modifyList(n.getClassBody(), arg);
@@ -410,11 +393,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final EnumDeclaration n, final A arg) {
         NodeList<EnumConstantDeclaration> entries = modifyList(n.getEntries(), arg);
         NodeList<ClassOrInterfaceType> implementedTypes = modifyList(n.getImplementedTypes(), arg);
         NodeList<BodyDeclaration<?>> members = modifyList(n.getMembers(), arg);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -423,6 +406,7 @@
         n.setEntries(entries);
         n.setImplementedTypes(implementedTypes);
         n.setMembers(members);
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setAnnotations(annotations);
         n.setComment(comment);
@@ -430,7 +414,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ExplicitConstructorInvocationStmt n, final A arg) {
         NodeList<Expression> arguments = modifyList(n.getArguments(), arg);
         Expression expression = n.getExpression().map(s -> (Expression) s.accept(this, arg)).orElse(null);
@@ -444,7 +427,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ExpressionStmt n, final A arg) {
         Expression expression = (Expression) n.getExpression().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -456,7 +438,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final FieldAccessExpr n, final A arg) {
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         Expression scope = (Expression) n.getScope().accept(this, arg);
@@ -472,13 +453,14 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final FieldDeclaration n, final A arg) {
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         NodeList<VariableDeclarator> variables = modifyList(n.getVariables(), arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         if (variables.isEmpty())
             return null;
+        n.setModifiers(modifiers);
         n.setVariables(variables);
         n.setAnnotations(annotations);
         n.setComment(comment);
@@ -486,8 +468,7 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
-    public Visitable visit(final ForeachStmt n, final A arg) {
+    public Visitable visit(final ForEachStmt n, final A arg) {
         Statement body = (Statement) n.getBody().accept(this, arg);
         Expression iterable = (Expression) n.getIterable().accept(this, arg);
         VariableDeclarationExpr variable = (VariableDeclarationExpr) n.getVariable().accept(this, arg);
@@ -502,7 +483,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ForStmt n, final A arg) {
         Statement body = (Statement) n.getBody().accept(this, arg);
         Expression compare = n.getCompare().map(s -> (Expression) s.accept(this, arg)).orElse(null);
@@ -520,7 +500,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final IfStmt n, final A arg) {
         Expression condition = (Expression) n.getCondition().accept(this, arg);
         Statement elseStmt = n.getElseStmt().map(s -> (Statement) s.accept(this, arg)).orElse(null);
@@ -536,7 +515,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final InitializerDeclaration n, final A arg) {
         BlockStmt body = (BlockStmt) n.getBody().accept(this, arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
@@ -550,7 +528,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final InstanceOfExpr n, final A arg) {
         Expression expression = (Expression) n.getExpression().accept(this, arg);
         ReferenceType type = (ReferenceType) n.getType().accept(this, arg);
@@ -564,7 +541,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final IntegerLiteralExpr n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -572,7 +548,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final JavadocComment n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -580,7 +555,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final LabeledStmt n, final A arg) {
         SimpleName label = (SimpleName) n.getLabel().accept(this, arg);
         Statement statement = (Statement) n.getStatement().accept(this, arg);
@@ -594,7 +568,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final LongLiteralExpr n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -602,7 +575,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final MarkerAnnotationExpr n, final A arg) {
         Name name = (Name) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -614,7 +586,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final MemberValuePair n, final A arg) {
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         Expression value = (Expression) n.getValue().accept(this, arg);
@@ -628,7 +599,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final MethodCallExpr n, final A arg) {
         NodeList<Expression> arguments = modifyList(n.getArguments(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
@@ -646,10 +616,10 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final MethodDeclaration n, final A arg) {
         BlockStmt body = n.getBody().map(s -> (BlockStmt) s.accept(this, arg)).orElse(null);
         Type type = (Type) n.getType().accept(this, arg);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         NodeList<Parameter> parameters = modifyList(n.getParameters(), arg);
         ReceiverParameter receiverParameter = n.getReceiverParameter().map(s -> (ReceiverParameter) s.accept(this, arg)).orElse(null);
@@ -661,6 +631,7 @@
             return null;
         n.setBody(body);
         n.setType(type);
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setParameters(parameters);
         n.setReceiverParameter(receiverParameter);
@@ -672,7 +643,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final NameExpr n, final A arg) {
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -684,7 +654,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final NormalAnnotationExpr n, final A arg) {
         NodeList<MemberValuePair> pairs = modifyList(n.getPairs(), arg);
         Name name = (Name) n.getName().accept(this, arg);
@@ -698,7 +667,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final NullLiteralExpr n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -706,7 +674,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ObjectCreationExpr n, final A arg) {
         NodeList<BodyDeclaration<?>> anonymousClassBody = modifyList(n.getAnonymousClassBody(), arg);
         NodeList<Expression> arguments = modifyList(n.getArguments(), arg);
@@ -726,7 +693,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final PackageDeclaration n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Name name = (Name) n.getName().accept(this, arg);
@@ -740,9 +706,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final Parameter n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         Type type = (Type) n.getType().accept(this, arg);
         NodeList<AnnotationExpr> varArgsAnnotations = modifyList(n.getVarArgsAnnotations(), arg);
@@ -750,6 +716,7 @@
         if (name == null || type == null)
             return null;
         n.setAnnotations(annotations);
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setType(type);
         n.setVarArgsAnnotations(varArgsAnnotations);
@@ -758,19 +725,15 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final Name n, final A arg) {
-        NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Name qualifier = n.getQualifier().map(s -> (Name) s.accept(this, arg)).orElse(null);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
-        n.setAnnotations(annotations);
         n.setQualifier(qualifier);
         n.setComment(comment);
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final PrimitiveType n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -780,7 +743,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final SimpleName n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -788,7 +750,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ArrayType n, final A arg) {
         Type componentType = (Type) n.getComponentType().accept(this, arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
@@ -802,7 +763,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ArrayCreationLevel n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Expression dimension = n.getDimension().map(s -> (Expression) s.accept(this, arg)).orElse(null);
@@ -814,7 +774,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final IntersectionType n, final A arg) {
         NodeList<ReferenceType> elements = modifyList(n.getElements(), arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
@@ -828,7 +787,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final UnionType n, final A arg) {
         NodeList<ReferenceType> elements = modifyList(n.getElements(), arg);
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
@@ -842,7 +800,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ReturnStmt n, final A arg) {
         Expression expression = n.getExpression().map(s -> (Expression) s.accept(this, arg)).orElse(null);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -852,7 +809,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final SingleMemberAnnotationExpr n, final A arg) {
         Expression memberValue = (Expression) n.getMemberValue().accept(this, arg);
         Name name = (Name) n.getName().accept(this, arg);
@@ -866,7 +822,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final StringLiteralExpr n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -874,31 +829,28 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final SuperExpr n, final A arg) {
-        Expression classExpr = n.getClassExpr().map(s -> (Expression) s.accept(this, arg)).orElse(null);
+        Name typeName = n.getTypeName().map(s -> (Name) s.accept(this, arg)).orElse(null);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
-        n.setClassExpr(classExpr);
+        n.setTypeName(typeName);
         n.setComment(comment);
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
-    public Visitable visit(final SwitchEntryStmt n, final A arg) {
-        Expression label = n.getLabel().map(s -> (Expression) s.accept(this, arg)).orElse(null);
+    public Visitable visit(final SwitchEntry n, final A arg) {
+        NodeList<Expression> labels = modifyList(n.getLabels(), arg);
         NodeList<Statement> statements = modifyList(n.getStatements(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
-        n.setLabel(label);
+        n.setLabels(labels);
         n.setStatements(statements);
         n.setComment(comment);
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final SwitchStmt n, final A arg) {
-        NodeList<SwitchEntryStmt> entries = modifyList(n.getEntries(), arg);
+        NodeList<SwitchEntry> entries = modifyList(n.getEntries(), arg);
         Expression selector = (Expression) n.getSelector().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         if (selector == null)
@@ -910,7 +862,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final SynchronizedStmt n, final A arg) {
         BlockStmt body = (BlockStmt) n.getBody().accept(this, arg);
         Expression expression = (Expression) n.getExpression().accept(this, arg);
@@ -924,17 +875,15 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ThisExpr n, final A arg) {
-        Expression classExpr = n.getClassExpr().map(s -> (Expression) s.accept(this, arg)).orElse(null);
+        Name typeName = n.getTypeName().map(s -> (Name) s.accept(this, arg)).orElse(null);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
-        n.setClassExpr(classExpr);
+        n.setTypeName(typeName);
         n.setComment(comment);
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ThrowStmt n, final A arg) {
         Expression expression = (Expression) n.getExpression().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -946,7 +895,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final TryStmt n, final A arg) {
         NodeList<CatchClause> catchClauses = modifyList(n.getCatchClauses(), arg);
         BlockStmt finallyBlock = n.getFinallyBlock().map(s -> (BlockStmt) s.accept(this, arg)).orElse(null);
@@ -964,7 +912,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final LocalClassDeclarationStmt n, final A arg) {
         ClassOrInterfaceDeclaration classDeclaration = (ClassOrInterfaceDeclaration) n.getClassDeclaration().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -976,7 +923,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final TypeParameter n, final A arg) {
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
         NodeList<ClassOrInterfaceType> typeBound = modifyList(n.getTypeBound(), arg);
@@ -992,7 +938,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final UnaryExpr n, final A arg) {
         Expression expression = (Expression) n.getExpression().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -1004,7 +949,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final UnknownType n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -1014,21 +958,21 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final VariableDeclarationExpr n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         NodeList<VariableDeclarator> variables = modifyList(n.getVariables(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         if (variables.isEmpty())
             return null;
         n.setAnnotations(annotations);
+        n.setModifiers(modifiers);
         n.setVariables(variables);
         n.setComment(comment);
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final VariableDeclarator n, final A arg) {
         Expression initializer = n.getInitializer().map(s -> (Expression) s.accept(this, arg)).orElse(null);
         SimpleName name = (SimpleName) n.getName().accept(this, arg);
@@ -1044,7 +988,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final VoidType n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -1054,7 +997,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final WhileStmt n, final A arg) {
         Statement body = (Statement) n.getBody().accept(this, arg);
         Expression condition = (Expression) n.getCondition().accept(this, arg);
@@ -1068,7 +1010,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final WildcardType n, final A arg) {
         ReferenceType extendedType = n.getExtendedType().map(s -> (ReferenceType) s.accept(this, arg)).orElse(null);
         ReferenceType superType = n.getSuperType().map(s -> (ReferenceType) s.accept(this, arg)).orElse(null);
@@ -1082,7 +1023,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final LambdaExpr n, final A arg) {
         Statement body = (Statement) n.getBody().accept(this, arg);
         NodeList<Parameter> parameters = modifyList(n.getParameters(), arg);
@@ -1096,7 +1036,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final MethodReferenceExpr n, final A arg) {
         Expression scope = (Expression) n.getScope().accept(this, arg);
         NodeList<Type> typeArguments = modifyList(n.getTypeArguments(), arg);
@@ -1110,7 +1049,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final TypeExpr n, final A arg) {
         Type type = (Type) n.getType().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -1134,20 +1072,15 @@
         }
         for (Pair<Node, Node> change : changeList) {
             if (change.b == null) {
-                n.remove(change.a);
+                removeElementByObjectIdentity(n, change.a);
             } else {
-                final int i = n.indexOf(change.a);
-                // If the user removed this item by hand, ignore the change.
-                if (i != -1) {
-                    n.set(i, change.b);
-                }
+                replaceElementByObjectIdentity(n, change.a, change.b);
             }
         }
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Node visit(final ImportDeclaration n, final A arg) {
         Name name = (Name) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -1159,7 +1092,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final BlockComment n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -1167,7 +1099,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final LineComment n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -1182,35 +1113,34 @@
         return list.map(ns -> modifyList(ns, arg)).orElse(null);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ModuleDeclaration n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
-        NodeList<ModuleStmt> moduleStmts = modifyList(n.getModuleStmts(), arg);
+        NodeList<ModuleDirective> directives = modifyList(n.getDirectives(), arg);
         Name name = (Name) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         if (name == null)
             return null;
         n.setAnnotations(annotations);
-        n.setModuleStmts(moduleStmts);
+        n.setDirectives(directives);
         n.setName(name);
         n.setComment(comment);
         return n;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
-    public Visitable visit(final ModuleRequiresStmt n, final A arg) {
+    public Visitable visit(final ModuleRequiresDirective n, final A arg) {
+        NodeList<Modifier> modifiers = modifyList(n.getModifiers(), arg);
         Name name = (Name) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         if (name == null)
             return null;
+        n.setModifiers(modifiers);
         n.setName(name);
         n.setComment(comment);
         return n;
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
-    public Visitable visit(final ModuleExportsStmt n, final A arg) {
+    public Visitable visit(final ModuleExportsDirective n, final A arg) {
         NodeList<Name> moduleNames = modifyList(n.getModuleNames(), arg);
         Name name = (Name) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -1223,34 +1153,31 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
-    public Visitable visit(final ModuleProvidesStmt n, final A arg) {
-        Type type = (Type) n.getType().accept(this, arg);
-        NodeList<Type> withTypes = modifyList(n.getWithTypes(), arg);
+    public Visitable visit(final ModuleProvidesDirective n, final A arg) {
+        Name name = (Name) n.getName().accept(this, arg);
+        NodeList<Name> with = modifyList(n.getWith(), arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
-        if (type == null)
+        if (name == null)
             return null;
-        n.setType(type);
-        n.setWithTypes(withTypes);
+        n.setName(name);
+        n.setWith(with);
         n.setComment(comment);
         return n;
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
-    public Visitable visit(final ModuleUsesStmt n, final A arg) {
-        Type type = (Type) n.getType().accept(this, arg);
+    public Visitable visit(final ModuleUsesDirective n, final A arg) {
+        Name name = (Name) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
-        if (type == null)
+        if (name == null)
             return null;
-        n.setType(type);
+        n.setName(name);
         n.setComment(comment);
         return n;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
-    public Visitable visit(final ModuleOpensStmt n, final A arg) {
+    public Visitable visit(final ModuleOpensDirective n, final A arg) {
         NodeList<Name> moduleNames = modifyList(n.getModuleNames(), arg);
         Name name = (Name) n.getName().accept(this, arg);
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
@@ -1263,7 +1190,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final UnparsableStmt n, final A arg) {
         Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
         n.setComment(comment);
@@ -1271,7 +1197,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ModifierVisitorGenerator")
     public Visitable visit(final ReceiverParameter n, final A arg) {
         NodeList<AnnotationExpr> annotations = modifyList(n.getAnnotations(), arg);
         Name name = (Name) n.getName().accept(this, arg);
@@ -1294,4 +1219,24 @@
         n.setComment(comment);
         return n;
     }
+
+    @Override
+    public Visitable visit(final Modifier n, final A arg) {
+        Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
+        n.setComment(comment);
+        return n;
+    }
+
+    @Override
+    public Visitable visit(final SwitchExpr n, final A arg) {
+        NodeList<SwitchEntry> entries = modifyList(n.getEntries(), arg);
+        Expression selector = (Expression) n.getSelector().accept(this, arg);
+        Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null);
+        if (selector == null)
+            return null;
+        n.setEntries(entries);
+        n.setSelector(selector);
+        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 b3c1dce..823a63e 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 import java.util.Optional;
 
 public class NoCommentEqualsVisitor implements GenericVisitor<Boolean, Visitable> {
@@ -90,7 +89,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final CompilationUnit n, final Visitable arg) {
         final CompilationUnit n2 = (CompilationUnit) arg;
         if (!nodesEquals(n.getImports(), n2.getImports()))
@@ -105,7 +103,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final PackageDeclaration n, final Visitable arg) {
         final PackageDeclaration n2 = (PackageDeclaration) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -116,7 +113,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final TypeParameter n, final Visitable arg) {
         final TypeParameter n2 = (TypeParameter) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -129,19 +125,16 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final LineComment n, final Visitable arg) {
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final BlockComment n, final Visitable arg) {
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ClassOrInterfaceDeclaration n, final Visitable arg) {
         final ClassOrInterfaceDeclaration n2 = (ClassOrInterfaceDeclaration) arg;
         if (!nodesEquals(n.getExtendedTypes(), n2.getExtendedTypes()))
@@ -154,7 +147,7 @@
             return false;
         if (!nodesEquals(n.getMembers(), n2.getMembers()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -164,7 +157,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final EnumDeclaration n, final Visitable arg) {
         final EnumDeclaration n2 = (EnumDeclaration) arg;
         if (!nodesEquals(n.getEntries(), n2.getEntries()))
@@ -173,7 +165,7 @@
             return false;
         if (!nodesEquals(n.getMembers(), n2.getMembers()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -183,7 +175,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final EnumConstantDeclaration n, final Visitable arg) {
         final EnumConstantDeclaration n2 = (EnumConstantDeclaration) arg;
         if (!nodesEquals(n.getArguments(), n2.getArguments()))
@@ -198,12 +189,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final AnnotationDeclaration n, final Visitable arg) {
         final AnnotationDeclaration n2 = (AnnotationDeclaration) arg;
         if (!nodesEquals(n.getMembers(), n2.getMembers()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -213,12 +203,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final AnnotationMemberDeclaration n, final Visitable arg) {
         final AnnotationMemberDeclaration n2 = (AnnotationMemberDeclaration) arg;
         if (!nodeEquals(n.getDefaultValue(), n2.getDefaultValue()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -230,10 +219,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final FieldDeclaration n, final Visitable arg) {
         final FieldDeclaration n2 = (FieldDeclaration) arg;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodesEquals(n.getVariables(), n2.getVariables()))
             return false;
@@ -243,7 +231,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final VariableDeclarator n, final Visitable arg) {
         final VariableDeclarator n2 = (VariableDeclarator) arg;
         if (!nodeEquals(n.getInitializer(), n2.getInitializer()))
@@ -256,12 +243,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ConstructorDeclaration n, final Visitable arg) {
         final ConstructorDeclaration n2 = (ConstructorDeclaration) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -279,14 +265,13 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final MethodDeclaration n, final Visitable arg) {
         final MethodDeclaration n2 = (MethodDeclaration) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
             return false;
         if (!nodeEquals(n.getType(), n2.getType()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -304,14 +289,13 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final Parameter n, final Visitable arg) {
         final Parameter n2 = (Parameter) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
             return false;
         if (!objEquals(n.isVarArgs(), n2.isVarArgs()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -323,7 +307,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final InitializerDeclaration n, final Visitable arg) {
         final InitializerDeclaration n2 = (InitializerDeclaration) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -336,13 +319,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final JavadocComment n, final Visitable arg) {
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ClassOrInterfaceType n, final Visitable arg) {
         final ClassOrInterfaceType n2 = (ClassOrInterfaceType) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -357,7 +338,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final PrimitiveType n, final Visitable arg) {
         final PrimitiveType n2 = (PrimitiveType) arg;
         if (!objEquals(n.getType(), n2.getType()))
@@ -368,7 +348,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ArrayType n, final Visitable arg) {
         final ArrayType n2 = (ArrayType) arg;
         if (!nodeEquals(n.getComponentType(), n2.getComponentType()))
@@ -381,7 +360,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ArrayCreationLevel n, final Visitable arg) {
         final ArrayCreationLevel n2 = (ArrayCreationLevel) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -392,7 +370,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final IntersectionType n, final Visitable arg) {
         final IntersectionType n2 = (IntersectionType) arg;
         if (!nodesEquals(n.getElements(), n2.getElements()))
@@ -403,7 +380,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final UnionType n, final Visitable arg) {
         final UnionType n2 = (UnionType) arg;
         if (!nodesEquals(n.getElements(), n2.getElements()))
@@ -414,7 +390,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final VoidType n, final Visitable arg) {
         final VoidType n2 = (VoidType) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -423,7 +398,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final WildcardType n, final Visitable arg) {
         final WildcardType n2 = (WildcardType) arg;
         if (!nodeEquals(n.getExtendedType(), n2.getExtendedType()))
@@ -436,7 +410,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final UnknownType n, final Visitable arg) {
         final UnknownType n2 = (UnknownType) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -445,7 +418,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ArrayAccessExpr n, final Visitable arg) {
         final ArrayAccessExpr n2 = (ArrayAccessExpr) arg;
         if (!nodeEquals(n.getIndex(), n2.getIndex()))
@@ -456,7 +428,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ArrayCreationExpr n, final Visitable arg) {
         final ArrayCreationExpr n2 = (ArrayCreationExpr) arg;
         if (!nodeEquals(n.getElementType(), n2.getElementType()))
@@ -469,7 +440,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ArrayInitializerExpr n, final Visitable arg) {
         final ArrayInitializerExpr n2 = (ArrayInitializerExpr) arg;
         if (!nodesEquals(n.getValues(), n2.getValues()))
@@ -478,7 +448,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final AssignExpr n, final Visitable arg) {
         final AssignExpr n2 = (AssignExpr) arg;
         if (!objEquals(n.getOperator(), n2.getOperator()))
@@ -491,7 +460,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final BinaryExpr n, final Visitable arg) {
         final BinaryExpr n2 = (BinaryExpr) arg;
         if (!nodeEquals(n.getLeft(), n2.getLeft()))
@@ -504,7 +472,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final CastExpr n, final Visitable arg) {
         final CastExpr n2 = (CastExpr) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -515,7 +482,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ClassExpr n, final Visitable arg) {
         final ClassExpr n2 = (ClassExpr) arg;
         if (!nodeEquals(n.getType(), n2.getType()))
@@ -524,7 +490,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ConditionalExpr n, final Visitable arg) {
         final ConditionalExpr n2 = (ConditionalExpr) arg;
         if (!nodeEquals(n.getCondition(), n2.getCondition()))
@@ -537,7 +502,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final EnclosedExpr n, final Visitable arg) {
         final EnclosedExpr n2 = (EnclosedExpr) arg;
         if (!nodeEquals(n.getInner(), n2.getInner()))
@@ -546,7 +510,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final FieldAccessExpr n, final Visitable arg) {
         final FieldAccessExpr n2 = (FieldAccessExpr) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -559,7 +522,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final InstanceOfExpr n, final Visitable arg) {
         final InstanceOfExpr n2 = (InstanceOfExpr) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -570,7 +532,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final StringLiteralExpr n, final Visitable arg) {
         final StringLiteralExpr n2 = (StringLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -579,7 +540,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final IntegerLiteralExpr n, final Visitable arg) {
         final IntegerLiteralExpr n2 = (IntegerLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -588,7 +548,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final LongLiteralExpr n, final Visitable arg) {
         final LongLiteralExpr n2 = (LongLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -597,7 +556,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final CharLiteralExpr n, final Visitable arg) {
         final CharLiteralExpr n2 = (CharLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -606,7 +564,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final DoubleLiteralExpr n, final Visitable arg) {
         final DoubleLiteralExpr n2 = (DoubleLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -615,7 +572,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final BooleanLiteralExpr n, final Visitable arg) {
         final BooleanLiteralExpr n2 = (BooleanLiteralExpr) arg;
         if (!objEquals(n.getValue(), n2.getValue()))
@@ -624,13 +580,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final NullLiteralExpr n, final Visitable arg) {
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final MethodCallExpr n, final Visitable arg) {
         final MethodCallExpr n2 = (MethodCallExpr) arg;
         if (!nodesEquals(n.getArguments(), n2.getArguments()))
@@ -645,7 +599,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final NameExpr n, final Visitable arg) {
         final NameExpr n2 = (NameExpr) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -654,7 +607,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ObjectCreationExpr n, final Visitable arg) {
         final ObjectCreationExpr n2 = (ObjectCreationExpr) arg;
         if (!nodesEquals(n.getAnonymousClassBody(), n2.getAnonymousClassBody()))
@@ -671,11 +623,8 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final Name n, final Visitable arg) {
         final Name n2 = (Name) arg;
-        if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
-            return false;
         if (!objEquals(n.getIdentifier(), n2.getIdentifier()))
             return false;
         if (!nodeEquals(n.getQualifier(), n2.getQualifier()))
@@ -684,7 +633,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final SimpleName n, final Visitable arg) {
         final SimpleName n2 = (SimpleName) arg;
         if (!objEquals(n.getIdentifier(), n2.getIdentifier()))
@@ -693,25 +641,22 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ThisExpr n, final Visitable arg) {
         final ThisExpr n2 = (ThisExpr) arg;
-        if (!nodeEquals(n.getClassExpr(), n2.getClassExpr()))
+        if (!nodeEquals(n.getTypeName(), n2.getTypeName()))
             return false;
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final SuperExpr n, final Visitable arg) {
         final SuperExpr n2 = (SuperExpr) arg;
-        if (!nodeEquals(n.getClassExpr(), n2.getClassExpr()))
+        if (!nodeEquals(n.getTypeName(), n2.getTypeName()))
             return false;
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final UnaryExpr n, final Visitable arg) {
         final UnaryExpr n2 = (UnaryExpr) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -722,12 +667,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final VariableDeclarationExpr n, final Visitable arg) {
         final VariableDeclarationExpr n2 = (VariableDeclarationExpr) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
             return false;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodesEquals(n.getVariables(), n2.getVariables()))
             return false;
@@ -735,7 +679,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final MarkerAnnotationExpr n, final Visitable arg) {
         final MarkerAnnotationExpr n2 = (MarkerAnnotationExpr) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -744,7 +687,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final SingleMemberAnnotationExpr n, final Visitable arg) {
         final SingleMemberAnnotationExpr n2 = (SingleMemberAnnotationExpr) arg;
         if (!nodeEquals(n.getMemberValue(), n2.getMemberValue()))
@@ -755,7 +697,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final NormalAnnotationExpr n, final Visitable arg) {
         final NormalAnnotationExpr n2 = (NormalAnnotationExpr) arg;
         if (!nodesEquals(n.getPairs(), n2.getPairs()))
@@ -766,7 +707,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final MemberValuePair n, final Visitable arg) {
         final MemberValuePair n2 = (MemberValuePair) arg;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -777,7 +717,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ExplicitConstructorInvocationStmt n, final Visitable arg) {
         final ExplicitConstructorInvocationStmt n2 = (ExplicitConstructorInvocationStmt) arg;
         if (!nodesEquals(n.getArguments(), n2.getArguments()))
@@ -792,7 +731,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final LocalClassDeclarationStmt n, final Visitable arg) {
         final LocalClassDeclarationStmt n2 = (LocalClassDeclarationStmt) arg;
         if (!nodeEquals(n.getClassDeclaration(), n2.getClassDeclaration()))
@@ -801,7 +739,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final AssertStmt n, final Visitable arg) {
         final AssertStmt n2 = (AssertStmt) arg;
         if (!nodeEquals(n.getCheck(), n2.getCheck()))
@@ -812,7 +749,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final BlockStmt n, final Visitable arg) {
         final BlockStmt n2 = (BlockStmt) arg;
         if (!nodesEquals(n.getStatements(), n2.getStatements()))
@@ -821,7 +757,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final LabeledStmt n, final Visitable arg) {
         final LabeledStmt n2 = (LabeledStmt) arg;
         if (!nodeEquals(n.getLabel(), n2.getLabel()))
@@ -832,13 +767,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final EmptyStmt n, final Visitable arg) {
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ExpressionStmt n, final Visitable arg) {
         final ExpressionStmt n2 = (ExpressionStmt) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -847,7 +780,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final SwitchStmt n, final Visitable arg) {
         final SwitchStmt n2 = (SwitchStmt) arg;
         if (!nodesEquals(n.getEntries(), n2.getEntries()))
@@ -858,27 +790,26 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final SwitchEntryStmt n, final Visitable arg) {
-        final SwitchEntryStmt n2 = (SwitchEntryStmt) arg;
-        if (!nodeEquals(n.getLabel(), n2.getLabel()))
+    public Boolean visit(final SwitchEntry n, final Visitable arg) {
+        final SwitchEntry n2 = (SwitchEntry) arg;
+        if (!nodesEquals(n.getLabels(), n2.getLabels()))
             return false;
         if (!nodesEquals(n.getStatements(), n2.getStatements()))
             return false;
-        return true;
-    }
-
-    @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final BreakStmt n, final Visitable arg) {
-        final BreakStmt n2 = (BreakStmt) arg;
-        if (!nodeEquals(n.getLabel(), n2.getLabel()))
+        if (!objEquals(n.getType(), n2.getType()))
             return false;
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
+    public Boolean visit(final BreakStmt n, final Visitable arg) {
+        final BreakStmt n2 = (BreakStmt) arg;
+        if (!nodeEquals(n.getValue(), n2.getValue()))
+            return false;
+        return true;
+    }
+
+    @Override
     public Boolean visit(final ReturnStmt n, final Visitable arg) {
         final ReturnStmt n2 = (ReturnStmt) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -887,7 +818,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final IfStmt n, final Visitable arg) {
         final IfStmt n2 = (IfStmt) arg;
         if (!nodeEquals(n.getCondition(), n2.getCondition()))
@@ -900,7 +830,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final WhileStmt n, final Visitable arg) {
         final WhileStmt n2 = (WhileStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -911,7 +840,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ContinueStmt n, final Visitable arg) {
         final ContinueStmt n2 = (ContinueStmt) arg;
         if (!nodeEquals(n.getLabel(), n2.getLabel()))
@@ -920,7 +848,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final DoStmt n, final Visitable arg) {
         final DoStmt n2 = (DoStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -931,9 +858,8 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final ForeachStmt n, final Visitable arg) {
-        final ForeachStmt n2 = (ForeachStmt) arg;
+    public Boolean visit(final ForEachStmt n, final Visitable arg) {
+        final ForEachStmt n2 = (ForEachStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
             return false;
         if (!nodeEquals(n.getIterable(), n2.getIterable()))
@@ -944,7 +870,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ForStmt n, final Visitable arg) {
         final ForStmt n2 = (ForStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -959,7 +884,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ThrowStmt n, final Visitable arg) {
         final ThrowStmt n2 = (ThrowStmt) arg;
         if (!nodeEquals(n.getExpression(), n2.getExpression()))
@@ -968,7 +892,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final SynchronizedStmt n, final Visitable arg) {
         final SynchronizedStmt n2 = (SynchronizedStmt) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -979,7 +902,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final TryStmt n, final Visitable arg) {
         final TryStmt n2 = (TryStmt) arg;
         if (!nodesEquals(n.getCatchClauses(), n2.getCatchClauses()))
@@ -994,7 +916,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final CatchClause n, final Visitable arg) {
         final CatchClause n2 = (CatchClause) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1005,7 +926,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final LambdaExpr n, final Visitable arg) {
         final LambdaExpr n2 = (LambdaExpr) arg;
         if (!nodeEquals(n.getBody(), n2.getBody()))
@@ -1018,7 +938,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final MethodReferenceExpr n, final Visitable arg) {
         final MethodReferenceExpr n2 = (MethodReferenceExpr) arg;
         if (!objEquals(n.getIdentifier(), n2.getIdentifier()))
@@ -1031,7 +950,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final TypeExpr n, final Visitable arg) {
         final TypeExpr n2 = (TypeExpr) arg;
         if (!nodeEquals(n.getType(), n2.getType()))
@@ -1040,7 +958,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ImportDeclaration n, final Visitable arg) {
         final ImportDeclaration n2 = (ImportDeclaration) arg;
         if (!objEquals(n.isAsterisk(), n2.isAsterisk()))
@@ -1058,25 +975,23 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ModuleDeclaration n, final Visitable arg) {
         final ModuleDeclaration n2 = (ModuleDeclaration) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
             return false;
+        if (!nodesEquals(n.getDirectives(), n2.getDirectives()))
+            return false;
         if (!objEquals(n.isOpen(), n2.isOpen()))
             return false;
-        if (!nodesEquals(n.getModuleStmts(), n2.getModuleStmts()))
-            return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final ModuleRequiresStmt n, final Visitable arg) {
-        final ModuleRequiresStmt n2 = (ModuleRequiresStmt) arg;
-        if (!objEquals(n.getModifiers(), n2.getModifiers()))
+    public Boolean visit(final ModuleRequiresDirective n, final Visitable arg) {
+        final ModuleRequiresDirective n2 = (ModuleRequiresDirective) arg;
+        if (!nodesEquals(n.getModifiers(), n2.getModifiers()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
             return false;
@@ -1084,9 +999,8 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final ModuleExportsStmt n, final Visitable arg) {
-        final ModuleExportsStmt n2 = (ModuleExportsStmt) arg;
+    public Boolean visit(final ModuleExportsDirective n, final Visitable arg) {
+        final ModuleExportsDirective n2 = (ModuleExportsDirective) arg;
         if (!nodesEquals(n.getModuleNames(), n2.getModuleNames()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -1095,29 +1009,26 @@
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final ModuleProvidesStmt n, final Visitable arg) {
-        final ModuleProvidesStmt n2 = (ModuleProvidesStmt) arg;
-        if (!nodeEquals(n.getType(), n2.getType()))
+    public Boolean visit(final ModuleProvidesDirective n, final Visitable arg) {
+        final ModuleProvidesDirective n2 = (ModuleProvidesDirective) arg;
+        if (!nodeEquals(n.getName(), n2.getName()))
             return false;
-        if (!nodesEquals(n.getWithTypes(), n2.getWithTypes()))
+        if (!nodesEquals(n.getWith(), n2.getWith()))
             return false;
         return true;
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final ModuleUsesStmt n, final Visitable arg) {
-        final ModuleUsesStmt n2 = (ModuleUsesStmt) arg;
-        if (!nodeEquals(n.getType(), n2.getType()))
+    public Boolean visit(final ModuleUsesDirective n, final Visitable arg) {
+        final ModuleUsesDirective n2 = (ModuleUsesDirective) arg;
+        if (!nodeEquals(n.getName(), n2.getName()))
             return false;
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
-    public Boolean visit(final ModuleOpensStmt n, final Visitable arg) {
-        final ModuleOpensStmt n2 = (ModuleOpensStmt) arg;
+    public Boolean visit(final ModuleOpensDirective n, final Visitable arg) {
+        final ModuleOpensDirective n2 = (ModuleOpensDirective) arg;
         if (!nodesEquals(n.getModuleNames(), n2.getModuleNames()))
             return false;
         if (!nodeEquals(n.getName(), n2.getName()))
@@ -1126,13 +1037,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final UnparsableStmt n, final Visitable arg) {
         return true;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentEqualsVisitorGenerator")
     public Boolean visit(final ReceiverParameter n, final Visitable arg) {
         final ReceiverParameter n2 = (ReceiverParameter) arg;
         if (!nodesEquals(n.getAnnotations(), n2.getAnnotations()))
@@ -1151,4 +1060,22 @@
             return false;
         return true;
     }
+
+    @Override
+    public Boolean visit(final Modifier n, final Visitable arg) {
+        final Modifier n2 = (Modifier) arg;
+        if (!objEquals(n.getKeyword(), n2.getKeyword()))
+            return false;
+        return true;
+    }
+
+    @Override
+    public Boolean visit(final SwitchExpr n, final Visitable arg) {
+        final SwitchExpr n2 = (SwitchExpr) arg;
+        if (!nodesEquals(n.getEntries(), n2.getEntries()))
+            return false;
+        if (!nodeEquals(n.getSelector(), n2.getSelector()))
+            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 774e5d9..7b2c661 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 public class NoCommentHashCodeVisitor implements GenericVisitor<Integer, Void> {
 
@@ -39,279 +38,224 @@
         return node.accept(SINGLETON, null);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final AnnotationDeclaration n, final Void arg) {
-        return (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
+        return (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final AnnotationMemberDeclaration n, final Void arg) {
-        return (n.getDefaultValue().isPresent() ? n.getDefaultValue().get().accept(this, arg) : 0) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
+        return (n.getDefaultValue().isPresent() ? n.getDefaultValue().get().accept(this, arg) : 0) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ArrayAccessExpr n, final Void arg) {
         return (n.getIndex().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ArrayCreationExpr n, final Void arg) {
         return (n.getElementType().accept(this, arg)) * 31 + (n.getInitializer().isPresent() ? n.getInitializer().get().accept(this, arg) : 0) * 31 + (n.getLevels().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ArrayCreationLevel n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getDimension().isPresent() ? n.getDimension().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ArrayInitializerExpr n, final Void arg) {
         return (n.getValues().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ArrayType n, final Void arg) {
         return (n.getComponentType().accept(this, arg)) * 31 + (n.getOrigin().hashCode()) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final AssertStmt n, final Void arg) {
         return (n.getCheck().accept(this, arg)) * 31 + (n.getMessage().isPresent() ? n.getMessage().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final AssignExpr n, final Void arg) {
         return (n.getOperator().hashCode()) * 31 + (n.getTarget().accept(this, arg)) * 31 + (n.getValue().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final BinaryExpr n, final Void arg) {
         return (n.getLeft().accept(this, arg)) * 31 + (n.getOperator().hashCode()) * 31 + (n.getRight().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final BlockComment n, final Void arg) {
         return 0;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final BlockStmt n, final Void arg) {
         return (n.getStatements().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final BooleanLiteralExpr n, final Void arg) {
         return (n.getValue() ? 1 : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final BreakStmt n, final Void arg) {
-        return (n.getLabel().isPresent() ? n.getLabel().get().accept(this, arg) : 0);
+        return (n.getValue().isPresent() ? n.getValue().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final CastExpr n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getType().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final CatchClause n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getParameter().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final CharLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ClassExpr n, final Void arg) {
         return (n.getType().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ClassOrInterfaceDeclaration n, final Void arg) {
-        return (n.getExtendedTypes().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.isInterface() ? 1 : 0) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
+        return (n.getExtendedTypes().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.isInterface() ? 1 : 0) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ClassOrInterfaceType n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getScope().isPresent() ? n.getScope().get().accept(this, arg) : 0) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final CompilationUnit n, final Void arg) {
         return (n.getImports().accept(this, arg)) * 31 + (n.getModule().isPresent() ? n.getModule().get().accept(this, arg) : 0) * 31 + (n.getPackageDeclaration().isPresent() ? n.getPackageDeclaration().get().accept(this, arg) : 0) * 31 + (n.getTypes().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ConditionalExpr n, final Void arg) {
         return (n.getCondition().accept(this, arg)) * 31 + (n.getElseExpr().accept(this, arg)) * 31 + (n.getThenExpr().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ConstructorDeclaration n, final Void arg) {
-        return (n.getBody().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
+        return (n.getBody().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ContinueStmt n, final Void arg) {
         return (n.getLabel().isPresent() ? n.getLabel().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final DoStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getCondition().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final DoubleLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final EmptyStmt n, final Void arg) {
         return 0;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final EnclosedExpr n, final Void arg) {
         return (n.getInner().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final EnumConstantDeclaration n, final Void arg) {
         return (n.getArguments().accept(this, arg)) * 31 + (n.getClassBody().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final EnumDeclaration n, final Void arg) {
-        return (n.getEntries().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
+        return (n.getEntries().accept(this, arg)) * 31 + (n.getImplementedTypes().accept(this, arg)) * 31 + (n.getMembers().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ExplicitConstructorInvocationStmt n, final Void arg) {
         return (n.getArguments().accept(this, arg)) * 31 + (n.getExpression().isPresent() ? n.getExpression().get().accept(this, arg) : 0) * 31 + (n.isThis() ? 1 : 0) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ExpressionStmt n, final Void arg) {
         return (n.getExpression().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final FieldAccessExpr n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getScope().accept(this, arg)) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final FieldDeclaration n, final Void arg) {
-        return (n.getModifiers().hashCode()) * 31 + (n.getVariables().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
+        return (n.getModifiers().accept(this, arg)) * 31 + (n.getVariables().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ForStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getCompare().isPresent() ? n.getCompare().get().accept(this, arg) : 0) * 31 + (n.getInitialization().accept(this, arg)) * 31 + (n.getUpdate().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
-    public Integer visit(final ForeachStmt n, final Void arg) {
+    public Integer visit(final ForEachStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getIterable().accept(this, arg)) * 31 + (n.getVariable().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final IfStmt n, final Void arg) {
         return (n.getCondition().accept(this, arg)) * 31 + (n.getElseStmt().isPresent() ? n.getElseStmt().get().accept(this, arg) : 0) * 31 + (n.getThenStmt().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ImportDeclaration n, final Void arg) {
         return (n.isAsterisk() ? 1 : 0) * 31 + (n.isStatic() ? 1 : 0) * 31 + (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final InitializerDeclaration n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.isStatic() ? 1 : 0) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final InstanceOfExpr n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getType().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final IntegerLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final IntersectionType n, final Void arg) {
         return (n.getElements().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final JavadocComment n, final Void arg) {
         return 0;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final LabeledStmt n, final Void arg) {
         return (n.getLabel().accept(this, arg)) * 31 + (n.getStatement().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final LambdaExpr n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.isEnclosingParameters() ? 1 : 0) * 31 + (n.getParameters().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final LineComment n, final Void arg) {
         return 0;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final LocalClassDeclarationStmt n, final Void arg) {
         return (n.getClassDeclaration().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final LongLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final MarkerAnnotationExpr n, final Void arg) {
         return (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final MemberValuePair n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getValue().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final MethodCallExpr n, final Void arg) {
         return (n.getArguments().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getScope().isPresent() ? n.getScope().get().accept(this, arg) : 0) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final MethodDeclaration n, final Void arg) {
-        return (n.getBody().isPresent() ? n.getBody().get().accept(this, arg) : 0) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
+        return (n.getBody().isPresent() ? n.getBody().get().accept(this, arg) : 0) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getParameters().accept(this, arg)) * 31 + (n.getReceiverParameter().isPresent() ? n.getReceiverParameter().get().accept(this, arg) : 0) * 31 + (n.getThrownExceptions().accept(this, arg)) * 31 + (n.getTypeParameters().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final MethodReferenceExpr n, final Void arg) {
         return (n.getIdentifier().hashCode()) * 31 + (n.getScope().accept(this, arg)) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final NameExpr n, final Void arg) {
         return (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final Name n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getIdentifier().hashCode()) * 31 + (n.getQualifier().isPresent() ? n.getQualifier().get().accept(this, arg) : 0);
+        return (n.getIdentifier().hashCode()) * 31 + (n.getQualifier().isPresent() ? n.getQualifier().get().accept(this, arg) : 0);
     }
 
     public Integer visit(NodeList n, Void arg) {
@@ -322,183 +266,148 @@
         return result;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final NormalAnnotationExpr n, final Void arg) {
         return (n.getPairs().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final NullLiteralExpr n, final Void arg) {
         return 0;
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ObjectCreationExpr n, final Void arg) {
         return (n.getAnonymousClassBody().isPresent() ? n.getAnonymousClassBody().get().accept(this, arg) : 0) * 31 + (n.getArguments().accept(this, arg)) * 31 + (n.getScope().isPresent() ? n.getScope().get().accept(this, arg) : 0) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getTypeArguments().isPresent() ? n.getTypeArguments().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final PackageDeclaration n, final Void arg) {
         return (n.getAnnotations().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final Parameter n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.isVarArgs() ? 1 : 0) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getVarArgsAnnotations().accept(this, arg));
+        return (n.getAnnotations().accept(this, arg)) * 31 + (n.isVarArgs() ? 1 : 0) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg)) * 31 + (n.getVarArgsAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final PrimitiveType n, final Void arg) {
         return (n.getType().hashCode()) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ReturnStmt n, final Void arg) {
         return (n.getExpression().isPresent() ? n.getExpression().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final SimpleName n, final Void arg) {
         return (n.getIdentifier().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final SingleMemberAnnotationExpr n, final Void arg) {
         return (n.getMemberValue().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final StringLiteralExpr n, final Void arg) {
         return (n.getValue().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final SuperExpr n, final Void arg) {
-        return (n.getClassExpr().isPresent() ? n.getClassExpr().get().accept(this, arg) : 0);
+        return (n.getTypeName().isPresent() ? n.getTypeName().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
-    public Integer visit(final SwitchEntryStmt n, final Void arg) {
-        return (n.getLabel().isPresent() ? n.getLabel().get().accept(this, arg) : 0) * 31 + (n.getStatements().accept(this, arg));
+    public Integer visit(final SwitchEntry n, final Void arg) {
+        return (n.getLabels().accept(this, arg)) * 31 + (n.getStatements().accept(this, arg)) * 31 + (n.getType().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final SwitchStmt n, final Void arg) {
         return (n.getEntries().accept(this, arg)) * 31 + (n.getSelector().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final SynchronizedStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getExpression().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ThisExpr n, final Void arg) {
-        return (n.getClassExpr().isPresent() ? n.getClassExpr().get().accept(this, arg) : 0);
+        return (n.getTypeName().isPresent() ? n.getTypeName().get().accept(this, arg) : 0);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ThrowStmt n, final Void arg) {
         return (n.getExpression().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final TryStmt n, final Void arg) {
         return (n.getCatchClauses().accept(this, arg)) * 31 + (n.getFinallyBlock().isPresent() ? n.getFinallyBlock().get().accept(this, arg) : 0) * 31 + (n.getResources().accept(this, arg)) * 31 + (n.getTryBlock().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final TypeExpr n, final Void arg) {
         return (n.getType().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final TypeParameter n, final Void arg) {
         return (n.getName().accept(this, arg)) * 31 + (n.getTypeBound().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final UnaryExpr n, final Void arg) {
         return (n.getExpression().accept(this, arg)) * 31 + (n.getOperator().hashCode());
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final UnionType n, final Void arg) {
         return (n.getElements().accept(this, arg)) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final UnknownType n, final Void arg) {
         return (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final VariableDeclarationExpr n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getModifiers().hashCode()) * 31 + (n.getVariables().accept(this, arg));
+        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getModifiers().accept(this, arg)) * 31 + (n.getVariables().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final VariableDeclarator n, final Void arg) {
         return (n.getInitializer().isPresent() ? n.getInitializer().get().accept(this, arg) : 0) * 31 + (n.getName().accept(this, arg)) * 31 + (n.getType().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final VoidType n, final Void arg) {
         return (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final WhileStmt n, final Void arg) {
         return (n.getBody().accept(this, arg)) * 31 + (n.getCondition().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final WildcardType n, final Void arg) {
         return (n.getExtendedType().isPresent() ? n.getExtendedType().get().accept(this, arg) : 0) * 31 + (n.getSuperType().isPresent() ? n.getSuperType().get().accept(this, arg) : 0) * 31 + (n.getAnnotations().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final ModuleDeclaration n, final Void arg) {
-        return (n.getAnnotations().accept(this, arg)) * 31 + (n.isOpen() ? 1 : 0) * 31 + (n.getModuleStmts().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
+        return (n.getAnnotations().accept(this, arg)) * 31 + (n.getDirectives().accept(this, arg)) * 31 + (n.isOpen() ? 1 : 0) * 31 + (n.getName().accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
-    public Integer visit(final ModuleRequiresStmt n, final Void arg) {
-        return (n.getModifiers().hashCode()) * 31 + (n.getName().accept(this, arg));
+    public Integer visit(final ModuleRequiresDirective n, final Void arg) {
+        return (n.getModifiers().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
-    public Integer visit(final ModuleExportsStmt n, final Void arg) {
+    public Integer visit(final ModuleExportsDirective n, final Void arg) {
         return (n.getModuleNames().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
-    public Integer visit(final ModuleProvidesStmt n, final Void arg) {
-        return (n.getType().accept(this, arg)) * 31 + (n.getWithTypes().accept(this, arg));
+    public Integer visit(final ModuleProvidesDirective n, final Void arg) {
+        return (n.getName().accept(this, arg)) * 31 + (n.getWith().accept(this, arg));
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
-    public Integer visit(final ModuleUsesStmt n, final Void arg) {
-        return (n.getType().accept(this, arg));
+    public Integer visit(final ModuleUsesDirective n, final Void arg) {
+        return (n.getName().accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
-    public Integer visit(final ModuleOpensStmt n, final Void arg) {
+    public Integer visit(final ModuleOpensDirective n, final Void arg) {
         return (n.getModuleNames().accept(this, arg)) * 31 + (n.getName().accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     public Integer visit(final UnparsableStmt n, final Void arg) {
         return 0;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.NoCommentHashCodeVisitorGenerator")
     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));
     }
@@ -507,4 +416,14 @@
     public Integer visit(final VarType n, final Void arg) {
         return (n.getAnnotations().accept(this, arg));
     }
+
+    @Override
+    public Integer visit(final Modifier n, final Void arg) {
+        return (n.getKeyword().hashCode());
+    }
+
+    @Override
+    public Integer visit(final SwitchExpr n, final Void arg) {
+        return (n.getEntries().accept(this, arg)) * 31 + (n.getSelector().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 7c642bb..c0aa2e9 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that calculates deep node equality by comparing all properties and child nodes of the node.
@@ -45,493 +44,411 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final CompilationUnit n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final PackageDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final TypeParameter n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final LineComment n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final BlockComment n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ClassOrInterfaceDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final EnumDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final EnumConstantDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final AnnotationDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final AnnotationMemberDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final FieldDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final VariableDeclarator n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ConstructorDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final MethodDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final Parameter n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final InitializerDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final JavadocComment n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ClassOrInterfaceType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final PrimitiveType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ArrayType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ArrayCreationLevel n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final IntersectionType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final UnionType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final VoidType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final WildcardType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final UnknownType n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ArrayAccessExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ArrayCreationExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ArrayInitializerExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final AssignExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final BinaryExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final CastExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ClassExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ConditionalExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final EnclosedExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final FieldAccessExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final InstanceOfExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final StringLiteralExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final IntegerLiteralExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final LongLiteralExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final CharLiteralExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final DoubleLiteralExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final BooleanLiteralExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final NullLiteralExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final MethodCallExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final NameExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ObjectCreationExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final Name n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final SimpleName n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ThisExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final SuperExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final UnaryExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final VariableDeclarationExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final MarkerAnnotationExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final SingleMemberAnnotationExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final NormalAnnotationExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final MemberValuePair n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ExplicitConstructorInvocationStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final LocalClassDeclarationStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final AssertStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final BlockStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final LabeledStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final EmptyStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ExpressionStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final SwitchStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
-    public Boolean visit(final SwitchEntryStmt n, final Visitable arg) {
+    public Boolean visit(final SwitchEntry n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final BreakStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ReturnStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final IfStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final WhileStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ContinueStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final DoStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
-    public Boolean visit(final ForeachStmt n, final Visitable arg) {
+    public Boolean visit(final ForEachStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ForStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ThrowStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final SynchronizedStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final TryStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final CatchClause n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final LambdaExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final MethodReferenceExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final TypeExpr n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ImportDeclaration n, final Visitable arg) {
         return n == arg;
     }
@@ -542,49 +459,41 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ModuleDeclaration n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
-    public Boolean visit(final ModuleRequiresStmt n, final Visitable arg) {
+    public Boolean visit(final ModuleRequiresDirective n, final Visitable arg) {
         return n == arg;
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
-    public Boolean visit(final ModuleExportsStmt n, final Visitable arg) {
+    public Boolean visit(final ModuleExportsDirective n, final Visitable arg) {
         return n == arg;
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
-    public Boolean visit(final ModuleProvidesStmt n, final Visitable arg) {
+    public Boolean visit(final ModuleProvidesDirective n, final Visitable arg) {
         return n == arg;
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
-    public Boolean visit(final ModuleUsesStmt n, final Visitable arg) {
+    public Boolean visit(final ModuleUsesDirective n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
-    public Boolean visit(final ModuleOpensStmt n, final Visitable arg) {
+    public Boolean visit(final ModuleOpensDirective n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final UnparsableStmt n, final Visitable arg) {
         return n == arg;
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityEqualsVisitorGenerator")
     public Boolean visit(final ReceiverParameter n, final Visitable arg) {
         return n == arg;
     }
@@ -593,4 +502,14 @@
     public Boolean visit(final VarType n, final Visitable arg) {
         return n == arg;
     }
+
+    @Override
+    public Boolean visit(final Modifier n, final Visitable arg) {
+        return n == arg;
+    }
+
+    @Override
+    public Boolean visit(final SwitchExpr 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 c53cf79..4a4dff3 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that calculates a deep hash code for a node by using the hash codes of all its properties,
@@ -43,277 +42,222 @@
         return node.accept(SINGLETON, null);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final AnnotationDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final AnnotationMemberDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ArrayAccessExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ArrayCreationExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ArrayCreationLevel n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ArrayInitializerExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ArrayType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final AssertStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final AssignExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final BinaryExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final BlockComment n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final BlockStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final BooleanLiteralExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final BreakStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final CastExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final CatchClause n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final CharLiteralExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ClassExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ClassOrInterfaceDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ClassOrInterfaceType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final CompilationUnit n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ConditionalExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ConstructorDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ContinueStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final DoStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final DoubleLiteralExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final EmptyStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final EnclosedExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final EnumConstantDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final EnumDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ExplicitConstructorInvocationStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ExpressionStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final FieldAccessExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final FieldDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ForStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
-    public Integer visit(final ForeachStmt n, final Void arg) {
+    public Integer visit(final ForEachStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final IfStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ImportDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final InitializerDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final InstanceOfExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final IntegerLiteralExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final IntersectionType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final JavadocComment n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final LabeledStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final LambdaExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final LineComment n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final LocalClassDeclarationStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final LongLiteralExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final MarkerAnnotationExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final MemberValuePair n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final MethodCallExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final MethodDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final MethodReferenceExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final NameExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final Name n, final Void arg) {
         return n.hashCode();
     }
@@ -322,183 +266,148 @@
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final NormalAnnotationExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final NullLiteralExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ObjectCreationExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final PackageDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final Parameter n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final PrimitiveType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ReturnStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final SimpleName n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final SingleMemberAnnotationExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final StringLiteralExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final SuperExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
-    public Integer visit(final SwitchEntryStmt n, final Void arg) {
+    public Integer visit(final SwitchEntry n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final SwitchStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final SynchronizedStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ThisExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ThrowStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final TryStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final TypeExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final TypeParameter n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final UnaryExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final UnionType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final UnknownType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final VariableDeclarationExpr n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final VariableDeclarator n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final VoidType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final WhileStmt n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final WildcardType n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ModuleDeclaration n, final Void arg) {
         return n.hashCode();
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
-    public Integer visit(final ModuleRequiresStmt n, final Void arg) {
+    public Integer visit(final ModuleRequiresDirective n, final Void arg) {
         return n.hashCode();
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
-    public Integer visit(final ModuleExportsStmt n, final Void arg) {
+    public Integer visit(final ModuleExportsDirective n, final Void arg) {
         return n.hashCode();
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
-    public Integer visit(final ModuleProvidesStmt n, final Void arg) {
+    public Integer visit(final ModuleProvidesDirective n, final Void arg) {
         return n.hashCode();
     }
 
     @Override()
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
-    public Integer visit(final ModuleUsesStmt n, final Void arg) {
+    public Integer visit(final ModuleUsesDirective n, final Void arg) {
         return n.hashCode();
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
-    public Integer visit(final ModuleOpensStmt n, final Void arg) {
+    public Integer visit(final ModuleOpensDirective n, final Void arg) {
         return n.hashCode();
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final UnparsableStmt n, final Void arg) {
         return n.hashCode();
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.ObjectIdentityHashCodeVisitorGenerator")
     public Integer visit(final ReceiverParameter n, final Void arg) {
         return n.hashCode();
     }
@@ -507,4 +416,14 @@
     public Integer visit(final VarType n, final Void arg) {
         return n.hashCode();
     }
+
+    @Override
+    public Integer visit(final Modifier n, final Void arg) {
+        return n.hashCode();
+    }
+
+    @Override
+    public Integer visit(final SwitchExpr n, final Void arg) {
+        return n.hashCode();
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/TreeVisitor.java b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/TreeVisitor.java
index 3c4aecd..b3205bd 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/TreeVisitor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/ast/visitor/TreeVisitor.java
@@ -66,19 +66,6 @@
     }
 
     /**
-     * Performs a pre-order node traversal starting with a given node. When each node is visited, {@link #process(Node)}
-     * is called for further processing.
-     *
-     * @param node The node at which the traversal begins.
-     * @see <a href="https://en.wikipedia.org/wiki/Pre-order">Pre-order traversal</a>
-     * @deprecated As of release 3.1.0, replaced by {@link #visitPreOrder(Node)}
-     */
-    @Deprecated
-    public void visitDepthFirst(Node node) {
-        visitPreOrder(node);
-    }
-
-    /**
      * https://en.wikipedia.org/wiki/Breadth-first_search
      *
      * @param node the start node, and the first one that is passed to process(node).
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 37c9c1c..b1b82c8 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that does not return anything.
@@ -40,275 +39,189 @@
 
     void visit(NodeList n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(AnnotationDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(AnnotationMemberDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ArrayAccessExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ArrayCreationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ArrayCreationLevel n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ArrayInitializerExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ArrayType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(AssertStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(AssignExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(BinaryExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(BlockComment n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(BlockStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(BooleanLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(BreakStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(CastExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(CatchClause n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(CharLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ClassExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ClassOrInterfaceDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ClassOrInterfaceType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(CompilationUnit n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ConditionalExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ConstructorDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ContinueStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(DoStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(DoubleLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(EmptyStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(EnclosedExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(EnumConstantDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(EnumDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ExplicitConstructorInvocationStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ExpressionStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(FieldAccessExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(FieldDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ForStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
-    void visit(ForeachStmt n, A arg);
+    void visit(ForEachStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(IfStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ImportDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(InitializerDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(InstanceOfExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(IntegerLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(IntersectionType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(JavadocComment n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(LabeledStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(LambdaExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(LineComment n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(LocalClassDeclarationStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(LongLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(MarkerAnnotationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(MemberValuePair n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(MethodCallExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(MethodDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(MethodReferenceExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(NameExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(Name n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(NormalAnnotationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(NullLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ObjectCreationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(PackageDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(Parameter n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(PrimitiveType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ReturnStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(SimpleName n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(SingleMemberAnnotationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(StringLiteralExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(SuperExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
-    void visit(SwitchEntryStmt n, A arg);
+    void visit(SwitchEntry n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(SwitchStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(SynchronizedStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ThisExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ThrowStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(TryStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(TypeExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(TypeParameter n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(UnaryExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(UnionType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(UnknownType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(VariableDeclarationExpr n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(VariableDeclarator n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(VoidType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(WhileStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(WildcardType n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ModuleDeclaration n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
-    void visit(ModuleRequiresStmt n, A arg);
+    void visit(ModuleRequiresDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
-    void visit(ModuleExportsStmt n, A arg);
+    void visit(ModuleExportsDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
-    void visit(ModuleProvidesStmt n, A arg);
+    void visit(ModuleProvidesDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
-    void visit(ModuleUsesStmt n, A arg);
+    void visit(ModuleUsesDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
-    void visit(ModuleOpensStmt n, A arg);
+    void visit(ModuleOpensDirective n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(UnparsableStmt n, A arg);
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorGenerator")
     void visit(ReceiverParameter n, A arg);
 
     void visit(VarType n, A arg);
+
+    void visit(Modifier n, A arg);
+
+    void visit(SwitchExpr switchExpr, 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 1ee8266..193ab50 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that returns nothing, and has a default implementation for all its visit
@@ -40,18 +39,18 @@
 public abstract class VoidVisitorAdapter<A> implements VoidVisitor<A> {
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final AnnotationDeclaration n, final A arg) {
         n.getMembers().forEach(p -> p.accept(this, arg));
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final AnnotationMemberDeclaration n, final A arg) {
         n.getDefaultValue().ifPresent(l -> l.accept(this, arg));
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getType().accept(this, arg);
         n.getAnnotations().forEach(p -> p.accept(this, arg));
@@ -59,7 +58,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ArrayAccessExpr n, final A arg) {
         n.getIndex().accept(this, arg);
         n.getName().accept(this, arg);
@@ -67,7 +65,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ArrayCreationExpr n, final A arg) {
         n.getElementType().accept(this, arg);
         n.getInitializer().ifPresent(l -> l.accept(this, arg));
@@ -76,14 +73,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ArrayInitializerExpr n, final A arg) {
         n.getValues().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final AssertStmt n, final A arg) {
         n.getCheck().accept(this, arg);
         n.getMessage().ifPresent(l -> l.accept(this, arg));
@@ -91,7 +86,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final AssignExpr n, final A arg) {
         n.getTarget().accept(this, arg);
         n.getValue().accept(this, arg);
@@ -99,7 +93,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final BinaryExpr n, final A arg) {
         n.getLeft().accept(this, arg);
         n.getRight().accept(this, arg);
@@ -107,33 +100,28 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final BlockComment n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final BlockStmt n, final A arg) {
         n.getStatements().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final BooleanLiteralExpr n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final BreakStmt n, final A arg) {
-        n.getLabel().ifPresent(l -> l.accept(this, arg));
+        n.getValue().ifPresent(l -> l.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final CastExpr n, final A arg) {
         n.getExpression().accept(this, arg);
         n.getType().accept(this, arg);
@@ -141,7 +129,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final CatchClause n, final A arg) {
         n.getBody().accept(this, arg);
         n.getParameter().accept(this, arg);
@@ -149,32 +136,29 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final CharLiteralExpr n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ClassExpr n, final A arg) {
         n.getType().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ClassOrInterfaceDeclaration n, final A arg) {
         n.getExtendedTypes().forEach(p -> p.accept(this, arg));
         n.getImplementedTypes().forEach(p -> p.accept(this, arg));
         n.getTypeParameters().forEach(p -> p.accept(this, arg));
         n.getMembers().forEach(p -> p.accept(this, arg));
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ClassOrInterfaceType n, final A arg) {
         n.getName().accept(this, arg);
         n.getScope().ifPresent(l -> l.accept(this, arg));
@@ -184,7 +168,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final CompilationUnit n, final A arg) {
         n.getImports().forEach(p -> p.accept(this, arg));
         n.getModule().ifPresent(l -> l.accept(this, arg));
@@ -194,7 +177,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ConditionalExpr n, final A arg) {
         n.getCondition().accept(this, arg);
         n.getElseExpr().accept(this, arg);
@@ -203,9 +185,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ConstructorDeclaration n, final A arg) {
         n.getBody().accept(this, arg);
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getParameters().forEach(p -> p.accept(this, arg));
         n.getReceiverParameter().ifPresent(l -> l.accept(this, arg));
@@ -216,14 +198,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ContinueStmt n, final A arg) {
         n.getLabel().ifPresent(l -> l.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final DoStmt n, final A arg) {
         n.getBody().accept(this, arg);
         n.getCondition().accept(this, arg);
@@ -231,26 +211,22 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final DoubleLiteralExpr n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final EmptyStmt n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final EnclosedExpr n, final A arg) {
         n.getInner().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final EnumConstantDeclaration n, final A arg) {
         n.getArguments().forEach(p -> p.accept(this, arg));
         n.getClassBody().forEach(p -> p.accept(this, arg));
@@ -260,18 +236,17 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final EnumDeclaration n, final A arg) {
         n.getEntries().forEach(p -> p.accept(this, arg));
         n.getImplementedTypes().forEach(p -> p.accept(this, arg));
         n.getMembers().forEach(p -> p.accept(this, arg));
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ExplicitConstructorInvocationStmt n, final A arg) {
         n.getArguments().forEach(p -> p.accept(this, arg));
         n.getExpression().ifPresent(l -> l.accept(this, arg));
@@ -280,14 +255,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ExpressionStmt n, final A arg) {
         n.getExpression().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final FieldAccessExpr n, final A arg) {
         n.getName().accept(this, arg);
         n.getScope().accept(this, arg);
@@ -296,16 +269,15 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final FieldDeclaration n, final A arg) {
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getVariables().forEach(p -> p.accept(this, arg));
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
-    public void visit(final ForeachStmt n, final A arg) {
+    public void visit(final ForEachStmt n, final A arg) {
         n.getBody().accept(this, arg);
         n.getIterable().accept(this, arg);
         n.getVariable().accept(this, arg);
@@ -313,7 +285,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ForStmt n, final A arg) {
         n.getBody().accept(this, arg);
         n.getCompare().ifPresent(l -> l.accept(this, arg));
@@ -323,7 +294,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final IfStmt n, final A arg) {
         n.getCondition().accept(this, arg);
         n.getElseStmt().ifPresent(l -> l.accept(this, arg));
@@ -332,7 +302,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final InitializerDeclaration n, final A arg) {
         n.getBody().accept(this, arg);
         n.getAnnotations().forEach(p -> p.accept(this, arg));
@@ -340,7 +309,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final InstanceOfExpr n, final A arg) {
         n.getExpression().accept(this, arg);
         n.getType().accept(this, arg);
@@ -348,19 +316,16 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final IntegerLiteralExpr n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final JavadocComment n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final LabeledStmt n, final A arg) {
         n.getLabel().accept(this, arg);
         n.getStatement().accept(this, arg);
@@ -368,26 +333,22 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final LineComment n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final LongLiteralExpr n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final MarkerAnnotationExpr n, final A arg) {
         n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final MemberValuePair n, final A arg) {
         n.getName().accept(this, arg);
         n.getValue().accept(this, arg);
@@ -395,7 +356,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final MethodCallExpr n, final A arg) {
         n.getArguments().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
@@ -405,10 +365,10 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final MethodDeclaration n, final A arg) {
         n.getBody().ifPresent(l -> l.accept(this, arg));
         n.getType().accept(this, arg);
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getParameters().forEach(p -> p.accept(this, arg));
         n.getReceiverParameter().ifPresent(l -> l.accept(this, arg));
@@ -419,14 +379,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final NameExpr n, final A arg) {
         n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final NormalAnnotationExpr n, final A arg) {
         n.getPairs().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
@@ -434,13 +392,11 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final NullLiteralExpr n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ObjectCreationExpr n, final A arg) {
         n.getAnonymousClassBody().ifPresent(l -> l.forEach(v -> v.accept(this, arg)));
         n.getArguments().forEach(p -> p.accept(this, arg));
@@ -451,7 +407,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final PackageDeclaration n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
@@ -459,9 +414,9 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final Parameter n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getType().accept(this, arg);
         n.getVarArgsAnnotations().forEach(p -> p.accept(this, arg));
@@ -469,28 +424,23 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final PrimitiveType n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final Name n, final A arg) {
-        n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getQualifier().ifPresent(l -> l.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final SimpleName n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ArrayType n, final A arg) {
         n.getComponentType().accept(this, arg);
         n.getAnnotations().forEach(p -> p.accept(this, arg));
@@ -498,7 +448,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ArrayCreationLevel n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getDimension().ifPresent(l -> l.accept(this, arg));
@@ -506,7 +455,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final IntersectionType n, final A arg) {
         n.getElements().forEach(p -> p.accept(this, arg));
         n.getAnnotations().forEach(p -> p.accept(this, arg));
@@ -514,7 +462,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final UnionType n, final A arg) {
         n.getElements().forEach(p -> p.accept(this, arg));
         n.getAnnotations().forEach(p -> p.accept(this, arg));
@@ -522,14 +469,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ReturnStmt n, final A arg) {
         n.getExpression().ifPresent(l -> l.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final SingleMemberAnnotationExpr n, final A arg) {
         n.getMemberValue().accept(this, arg);
         n.getName().accept(this, arg);
@@ -537,28 +482,24 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final StringLiteralExpr n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final SuperExpr n, final A arg) {
-        n.getClassExpr().ifPresent(l -> l.accept(this, arg));
+        n.getTypeName().ifPresent(l -> l.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
-    public void visit(final SwitchEntryStmt n, final A arg) {
-        n.getLabel().ifPresent(l -> l.accept(this, arg));
+    public void visit(final SwitchEntry n, final A arg) {
+        n.getLabels().forEach(p -> p.accept(this, arg));
         n.getStatements().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final SwitchStmt n, final A arg) {
         n.getEntries().forEach(p -> p.accept(this, arg));
         n.getSelector().accept(this, arg);
@@ -566,7 +507,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final SynchronizedStmt n, final A arg) {
         n.getBody().accept(this, arg);
         n.getExpression().accept(this, arg);
@@ -574,21 +514,18 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ThisExpr n, final A arg) {
-        n.getClassExpr().ifPresent(l -> l.accept(this, arg));
+        n.getTypeName().ifPresent(l -> l.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ThrowStmt n, final A arg) {
         n.getExpression().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final TryStmt n, final A arg) {
         n.getCatchClauses().forEach(p -> p.accept(this, arg));
         n.getFinallyBlock().ifPresent(l -> l.accept(this, arg));
@@ -598,14 +535,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final LocalClassDeclarationStmt n, final A arg) {
         n.getClassDeclaration().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final TypeParameter n, final A arg) {
         n.getName().accept(this, arg);
         n.getTypeBound().forEach(p -> p.accept(this, arg));
@@ -614,29 +549,26 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final UnaryExpr n, final A arg) {
         n.getExpression().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final UnknownType n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final VariableDeclarationExpr n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getVariables().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final VariableDeclarator n, final A arg) {
         n.getInitializer().ifPresent(l -> l.accept(this, arg));
         n.getName().accept(this, arg);
@@ -645,14 +577,12 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final VoidType n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final WhileStmt n, final A arg) {
         n.getBody().accept(this, arg);
         n.getCondition().accept(this, arg);
@@ -660,7 +590,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final WildcardType n, final A arg) {
         n.getExtendedType().ifPresent(l -> l.accept(this, arg));
         n.getSuperType().ifPresent(l -> l.accept(this, arg));
@@ -669,7 +598,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final LambdaExpr n, final A arg) {
         n.getBody().accept(this, arg);
         n.getParameters().forEach(p -> p.accept(this, arg));
@@ -677,7 +605,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final MethodReferenceExpr n, final A arg) {
         n.getScope().accept(this, arg);
         n.getTypeArguments().ifPresent(l -> l.forEach(v -> v.accept(this, arg)));
@@ -685,7 +612,6 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final TypeExpr n, final A arg) {
         n.getType().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
@@ -699,65 +625,57 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ImportDeclaration n, final A arg) {
         n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ModuleDeclaration n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
-        n.getModuleStmts().forEach(p -> p.accept(this, arg));
+        n.getDirectives().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
-    public void visit(final ModuleRequiresStmt n, final A arg) {
+    public void visit(final ModuleRequiresDirective n, final A arg) {
+        n.getModifiers().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
-    public void visit(final ModuleExportsStmt n, final A arg) {
+    public void visit(final ModuleExportsDirective n, final A arg) {
         n.getModuleNames().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
-    public void visit(final ModuleProvidesStmt n, final A arg) {
-        n.getType().accept(this, arg);
-        n.getWithTypes().forEach(p -> p.accept(this, arg));
+    public void visit(final ModuleProvidesDirective n, final A arg) {
+        n.getName().accept(this, arg);
+        n.getWith().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
-    public void visit(final ModuleUsesStmt n, final A arg) {
-        n.getType().accept(this, arg);
+    public void visit(final ModuleUsesDirective n, final A arg) {
+        n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
-    public void visit(final ModuleOpensStmt n, final A arg) {
+    public void visit(final ModuleOpensDirective n, final A arg) {
         n.getModuleNames().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final UnparsableStmt n, final A arg) {
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorAdapterGenerator")
     public void visit(final ReceiverParameter n, final A arg) {
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getName().accept(this, arg);
@@ -770,4 +688,16 @@
         n.getAnnotations().forEach(p -> p.accept(this, arg));
         n.getComment().ifPresent(l -> l.accept(this, arg));
     }
+
+    @Override
+    public void visit(final Modifier n, final A arg) {
+        n.getComment().ifPresent(l -> l.accept(this, arg));
+    }
+
+    @Override
+    public void visit(final SwitchExpr n, final A arg) {
+        n.getEntries().forEach(p -> p.accept(this, arg));
+        n.getSelector().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 6622567..8397fe9 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
@@ -29,7 +29,6 @@
 import com.github.javaparser.ast.modules.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
-import javax.annotation.Generated;
 
 /**
  * A visitor that returns nothing, and has default methods that are used when a specific visit method is not
@@ -50,487 +49,406 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final AnnotationDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final AnnotationMemberDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ArrayAccessExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ArrayCreationExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ArrayInitializerExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final AssertStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final AssignExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final BinaryExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final BlockComment n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final BlockStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final BooleanLiteralExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final BreakStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final CastExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final CatchClause n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final CharLiteralExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ClassExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ClassOrInterfaceDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ClassOrInterfaceType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final CompilationUnit n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ConditionalExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ConstructorDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ContinueStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final DoStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final DoubleLiteralExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final EmptyStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final EnclosedExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final EnumConstantDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final EnumDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ExplicitConstructorInvocationStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ExpressionStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final FieldAccessExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final FieldDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
-    public void visit(final ForeachStmt n, final A arg) {
+    public void visit(final ForEachStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ForStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final IfStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final InitializerDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final InstanceOfExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final IntegerLiteralExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final JavadocComment n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final LabeledStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final LineComment n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final LongLiteralExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final MarkerAnnotationExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final MemberValuePair n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final MethodCallExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final MethodDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final NameExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final NormalAnnotationExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final NullLiteralExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ObjectCreationExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final PackageDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final Parameter n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final PrimitiveType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final Name n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final SimpleName n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ArrayType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ArrayCreationLevel n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final IntersectionType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final UnionType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ReturnStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final SingleMemberAnnotationExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final StringLiteralExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final SuperExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
-    public void visit(final SwitchEntryStmt n, final A arg) {
+    public void visit(final SwitchEntry n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final SwitchStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final SynchronizedStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ThisExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ThrowStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final TryStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final LocalClassDeclarationStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final TypeParameter n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final UnaryExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final UnknownType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final VariableDeclarationExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final VariableDeclarator n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final VoidType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final WhileStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final WildcardType n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final LambdaExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final MethodReferenceExpr n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final TypeExpr n, final A arg) {
         defaultAction(n, arg);
     }
@@ -541,59 +459,60 @@
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ImportDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ModuleDeclaration n, final A arg) {
         defaultAction(n, arg);
     }
 
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
-    public void visit(final ModuleRequiresStmt n, final A arg) {
+    public void visit(final ModuleRequiresDirective n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
-    public void visit(final ModuleExportsStmt n, final A arg) {
+    public void visit(final ModuleExportsDirective n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
-    public void visit(final ModuleProvidesStmt n, final A arg) {
+    public void visit(final ModuleProvidesDirective n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
-    public void visit(final ModuleUsesStmt n, final A arg) {
+    public void visit(final ModuleUsesDirective n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
-    public void visit(final ModuleOpensStmt n, final A arg) {
+    public void visit(final ModuleOpensDirective n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final UnparsableStmt n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
-    @Generated("com.github.javaparser.generator.core.visitor.VoidVisitorWithDefaultsGenerator")
     public void visit(final ReceiverParameter n, final A arg) {
         defaultAction(n, arg);
     }
 
     @Override
+    public void visit(final Modifier n, final A arg) {
+        defaultAction(n, arg);
+    }
+
+    @Override
     public void visit(final VarType n, final A arg) {
         defaultAction(n, arg);
     }
+
+    @Override
+    public void visit(final SwitchExpr n, final A arg) {
+        defaultAction(n, arg);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocDescription.java b/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocDescription.java
index 82f818a..3a55d25 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocDescription.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocDescription.java
@@ -41,10 +41,10 @@
         Pair<Integer, Integer> nextInlineTagPos;
         while ((nextInlineTagPos = indexOfNextInlineTag(text, index)) != null) {
             if (nextInlineTagPos.a != index) {
-                instance.addElement(new JavadocSnippet(text.substring(index, nextInlineTagPos.a + 1)));
+                instance.addElement(new JavadocSnippet(text.substring(index, nextInlineTagPos.a)));
             }
             instance.addElement(JavadocInlineTag.fromText(text.substring(nextInlineTagPos.a, nextInlineTagPos.b + 1)));
-            index = nextInlineTagPos.b;
+            index = nextInlineTagPos.b + 1;
         }
         if (index < text.length()) {
             instance.addElement(new JavadocSnippet(text.substring(index)));
diff --git a/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocInlineTag.java b/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocInlineTag.java
index 8125bd5..d503041 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocInlineTag.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/javadoc/description/JavadocInlineTag.java
@@ -57,6 +57,7 @@
         LINKPLAIN,
         LITERAL,
         VALUE,
+        SYSTEM_PROPERTY,
         UNKNOWN;
 
         Type() {
@@ -86,9 +87,21 @@
         this.content = content;
     }
 
+    public Type getType() {
+        return type;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public String getName() {
+        return tagName;
+    }
+
     @Override
     public String toText() {
-        return "@" + tagName + this.content;
+        return "{@" + tagName + this.content +"}";
     }
 
     @Override
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/BaseNodeMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/BaseNodeMetaModel.java
index 86e53fd..eb7d766 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/BaseNodeMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/BaseNodeMetaModel.java
@@ -1,10 +1,12 @@
 package com.github.javaparser.metamodel;
 
+import com.github.javaparser.ast.AllFieldsConstructor;
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
 
 import static com.github.javaparser.utils.Utils.decapitalize;
 
@@ -177,4 +179,35 @@
     public String getMetaModelFieldName() {
         return decapitalize(getClass().getSimpleName());
     }
+
+    /**
+     * Creates a new node of this type.
+     *
+     * @param parameters a map of propertyName -> value.
+     * This should at least contain a pair for every required property for this node.
+     */
+    public Node construct(Map<String, Object> parameters) {
+        for (Constructor<?> constructor : getType().getConstructors()) {
+            if (constructor.getAnnotation(AllFieldsConstructor.class) != null) {
+                try {
+                    Object[] paramArray = new Object[constructor.getParameterCount()];
+                    int i = 0;
+                    for (PropertyMetaModel constructorParameter : getConstructorParameters()) {
+                        paramArray[i] = parameters.get(constructorParameter.getName());
+                        if (paramArray[i] == null && constructorParameter.isRequired()) {
+                            if (constructorParameter.isNodeList()) {
+                                paramArray[i] = new NodeList<>();
+                            }
+                            // We could have more defaults here.
+                        }
+                        i++;
+                    }
+                    return (Node) constructor.newInstance(paramArray);
+                } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        throw new IllegalStateException();
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/BreakStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/BreakStmtMetaModel.java
index 39f7232..394716c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/BreakStmtMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/BreakStmtMetaModel.java
@@ -8,5 +8,5 @@
         super(superBaseNodeMetaModel, com.github.javaparser.ast.stmt.BreakStmt.class, "BreakStmt", "com.github.javaparser.ast.stmt", false, false);
     }
 
-    public PropertyMetaModel labelPropertyMetaModel;
+    public PropertyMetaModel valuePropertyMetaModel;
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ForEachStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ForEachStmtMetaModel.java
new file mode 100644
index 0000000..c86f677
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ForEachStmtMetaModel.java
@@ -0,0 +1,16 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class ForEachStmtMetaModel extends StatementMetaModel {
+
+    ForEachStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.stmt.ForEachStmt.class, "ForEachStmt", "com.github.javaparser.ast.stmt", false, false);
+    }
+
+    public PropertyMetaModel bodyPropertyMetaModel;
+
+    public PropertyMetaModel iterablePropertyMetaModel;
+
+    public PropertyMetaModel variablePropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ForeachStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ForeachStmtMetaModel.java
deleted file mode 100644
index 8a8dc4e..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ForeachStmtMetaModel.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-
-public class ForeachStmtMetaModel extends StatementMetaModel {
-
-    ForeachStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.stmt.ForeachStmt.class, "ForeachStmt", "com.github.javaparser.ast.stmt", false, false);
-    }
-
-    public PropertyMetaModel bodyPropertyMetaModel;
-
-    public PropertyMetaModel iterablePropertyMetaModel;
-
-    public PropertyMetaModel variablePropertyMetaModel;
-}
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 bffbd37..69e1ec2 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
@@ -1,13 +1,9 @@
 package com.github.javaparser.metamodel;
 
-import com.github.javaparser.ast.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
-/**
- * The model contains meta-data about all nodes in the AST.
- */
 public final class JavaParserMetaModel {
 
     private JavaParserMetaModel() {
@@ -36,7 +32,7 @@
         moduleDeclarationMetaModel.getConstructorParameters().add(moduleDeclarationMetaModel.annotationsPropertyMetaModel);
         moduleDeclarationMetaModel.getConstructorParameters().add(moduleDeclarationMetaModel.namePropertyMetaModel);
         moduleDeclarationMetaModel.getConstructorParameters().add(moduleDeclarationMetaModel.isOpenPropertyMetaModel);
-        moduleDeclarationMetaModel.getConstructorParameters().add(moduleDeclarationMetaModel.moduleStmtsPropertyMetaModel);
+        moduleDeclarationMetaModel.getConstructorParameters().add(moduleDeclarationMetaModel.directivesPropertyMetaModel);
         arrayCreationLevelMetaModel.getConstructorParameters().add(arrayCreationLevelMetaModel.dimensionPropertyMetaModel);
         arrayCreationLevelMetaModel.getConstructorParameters().add(arrayCreationLevelMetaModel.annotationsPropertyMetaModel);
         compilationUnitMetaModel.getConstructorParameters().add(compilationUnitMetaModel.packageDeclarationPropertyMetaModel);
@@ -45,6 +41,7 @@
         compilationUnitMetaModel.getConstructorParameters().add(compilationUnitMetaModel.modulePropertyMetaModel);
         packageDeclarationMetaModel.getConstructorParameters().add(packageDeclarationMetaModel.annotationsPropertyMetaModel);
         packageDeclarationMetaModel.getConstructorParameters().add(packageDeclarationMetaModel.namePropertyMetaModel);
+        modifierMetaModel.getConstructorParameters().add(modifierMetaModel.keywordPropertyMetaModel);
         annotationDeclarationMetaModel.getConstructorParameters().add(typeDeclarationMetaModel.modifiersPropertyMetaModel);
         annotationDeclarationMetaModel.getConstructorParameters().add(bodyDeclarationMetaModel.annotationsPropertyMetaModel);
         annotationDeclarationMetaModel.getConstructorParameters().add(typeDeclarationMetaModel.namePropertyMetaModel);
@@ -155,7 +152,6 @@
         nameExprMetaModel.getConstructorParameters().add(nameExprMetaModel.namePropertyMetaModel);
         nameMetaModel.getConstructorParameters().add(nameMetaModel.qualifierPropertyMetaModel);
         nameMetaModel.getConstructorParameters().add(nameMetaModel.identifierPropertyMetaModel);
-        nameMetaModel.getConstructorParameters().add(nameMetaModel.annotationsPropertyMetaModel);
         normalAnnotationExprMetaModel.getConstructorParameters().add(annotationExprMetaModel.namePropertyMetaModel);
         normalAnnotationExprMetaModel.getConstructorParameters().add(normalAnnotationExprMetaModel.pairsPropertyMetaModel);
         objectCreationExprMetaModel.getConstructorParameters().add(objectCreationExprMetaModel.scopePropertyMetaModel);
@@ -166,21 +162,23 @@
         simpleNameMetaModel.getConstructorParameters().add(simpleNameMetaModel.identifierPropertyMetaModel);
         singleMemberAnnotationExprMetaModel.getConstructorParameters().add(annotationExprMetaModel.namePropertyMetaModel);
         singleMemberAnnotationExprMetaModel.getConstructorParameters().add(singleMemberAnnotationExprMetaModel.memberValuePropertyMetaModel);
-        superExprMetaModel.getConstructorParameters().add(superExprMetaModel.classExprPropertyMetaModel);
-        thisExprMetaModel.getConstructorParameters().add(thisExprMetaModel.classExprPropertyMetaModel);
+        superExprMetaModel.getConstructorParameters().add(superExprMetaModel.typeNamePropertyMetaModel);
+        thisExprMetaModel.getConstructorParameters().add(thisExprMetaModel.typeNamePropertyMetaModel);
         typeExprMetaModel.getConstructorParameters().add(typeExprMetaModel.typePropertyMetaModel);
         unaryExprMetaModel.getConstructorParameters().add(unaryExprMetaModel.expressionPropertyMetaModel);
         unaryExprMetaModel.getConstructorParameters().add(unaryExprMetaModel.operatorPropertyMetaModel);
         variableDeclarationExprMetaModel.getConstructorParameters().add(variableDeclarationExprMetaModel.modifiersPropertyMetaModel);
         variableDeclarationExprMetaModel.getConstructorParameters().add(variableDeclarationExprMetaModel.annotationsPropertyMetaModel);
         variableDeclarationExprMetaModel.getConstructorParameters().add(variableDeclarationExprMetaModel.variablesPropertyMetaModel);
+        switchExprMetaModel.getConstructorParameters().add(switchExprMetaModel.selectorPropertyMetaModel);
+        switchExprMetaModel.getConstructorParameters().add(switchExprMetaModel.entriesPropertyMetaModel);
         importDeclarationMetaModel.getConstructorParameters().add(importDeclarationMetaModel.namePropertyMetaModel);
         importDeclarationMetaModel.getConstructorParameters().add(importDeclarationMetaModel.isStaticPropertyMetaModel);
         importDeclarationMetaModel.getConstructorParameters().add(importDeclarationMetaModel.isAsteriskPropertyMetaModel);
         assertStmtMetaModel.getConstructorParameters().add(assertStmtMetaModel.checkPropertyMetaModel);
         assertStmtMetaModel.getConstructorParameters().add(assertStmtMetaModel.messagePropertyMetaModel);
         blockStmtMetaModel.getConstructorParameters().add(blockStmtMetaModel.statementsPropertyMetaModel);
-        breakStmtMetaModel.getConstructorParameters().add(breakStmtMetaModel.labelPropertyMetaModel);
+        breakStmtMetaModel.getConstructorParameters().add(breakStmtMetaModel.valuePropertyMetaModel);
         catchClauseMetaModel.getConstructorParameters().add(catchClauseMetaModel.parameterPropertyMetaModel);
         catchClauseMetaModel.getConstructorParameters().add(catchClauseMetaModel.bodyPropertyMetaModel);
         continueStmtMetaModel.getConstructorParameters().add(continueStmtMetaModel.labelPropertyMetaModel);
@@ -191,9 +189,9 @@
         explicitConstructorInvocationStmtMetaModel.getConstructorParameters().add(explicitConstructorInvocationStmtMetaModel.expressionPropertyMetaModel);
         explicitConstructorInvocationStmtMetaModel.getConstructorParameters().add(explicitConstructorInvocationStmtMetaModel.argumentsPropertyMetaModel);
         expressionStmtMetaModel.getConstructorParameters().add(expressionStmtMetaModel.expressionPropertyMetaModel);
-        foreachStmtMetaModel.getConstructorParameters().add(foreachStmtMetaModel.variablePropertyMetaModel);
-        foreachStmtMetaModel.getConstructorParameters().add(foreachStmtMetaModel.iterablePropertyMetaModel);
-        foreachStmtMetaModel.getConstructorParameters().add(foreachStmtMetaModel.bodyPropertyMetaModel);
+        forEachStmtMetaModel.getConstructorParameters().add(forEachStmtMetaModel.variablePropertyMetaModel);
+        forEachStmtMetaModel.getConstructorParameters().add(forEachStmtMetaModel.iterablePropertyMetaModel);
+        forEachStmtMetaModel.getConstructorParameters().add(forEachStmtMetaModel.bodyPropertyMetaModel);
         forStmtMetaModel.getConstructorParameters().add(forStmtMetaModel.initializationPropertyMetaModel);
         forStmtMetaModel.getConstructorParameters().add(forStmtMetaModel.comparePropertyMetaModel);
         forStmtMetaModel.getConstructorParameters().add(forStmtMetaModel.updatePropertyMetaModel);
@@ -204,8 +202,9 @@
         labeledStmtMetaModel.getConstructorParameters().add(labeledStmtMetaModel.labelPropertyMetaModel);
         labeledStmtMetaModel.getConstructorParameters().add(labeledStmtMetaModel.statementPropertyMetaModel);
         returnStmtMetaModel.getConstructorParameters().add(returnStmtMetaModel.expressionPropertyMetaModel);
-        switchEntryStmtMetaModel.getConstructorParameters().add(switchEntryStmtMetaModel.labelPropertyMetaModel);
-        switchEntryStmtMetaModel.getConstructorParameters().add(switchEntryStmtMetaModel.statementsPropertyMetaModel);
+        switchEntryMetaModel.getConstructorParameters().add(switchEntryMetaModel.labelsPropertyMetaModel);
+        switchEntryMetaModel.getConstructorParameters().add(switchEntryMetaModel.typePropertyMetaModel);
+        switchEntryMetaModel.getConstructorParameters().add(switchEntryMetaModel.statementsPropertyMetaModel);
         switchStmtMetaModel.getConstructorParameters().add(switchStmtMetaModel.selectorPropertyMetaModel);
         switchStmtMetaModel.getConstructorParameters().add(switchStmtMetaModel.entriesPropertyMetaModel);
         synchronizedStmtMetaModel.getConstructorParameters().add(synchronizedStmtMetaModel.expressionPropertyMetaModel);
@@ -235,15 +234,15 @@
         wildcardTypeMetaModel.getConstructorParameters().add(wildcardTypeMetaModel.extendedTypePropertyMetaModel);
         wildcardTypeMetaModel.getConstructorParameters().add(wildcardTypeMetaModel.superTypePropertyMetaModel);
         wildcardTypeMetaModel.getConstructorParameters().add(typeMetaModel.annotationsPropertyMetaModel);
-        moduleRequiresStmtMetaModel.getConstructorParameters().add(moduleRequiresStmtMetaModel.modifiersPropertyMetaModel);
-        moduleRequiresStmtMetaModel.getConstructorParameters().add(moduleRequiresStmtMetaModel.namePropertyMetaModel);
-        moduleExportsStmtMetaModel.getConstructorParameters().add(moduleExportsStmtMetaModel.namePropertyMetaModel);
-        moduleExportsStmtMetaModel.getConstructorParameters().add(moduleExportsStmtMetaModel.moduleNamesPropertyMetaModel);
-        moduleProvidesStmtMetaModel.getConstructorParameters().add(moduleProvidesStmtMetaModel.typePropertyMetaModel);
-        moduleProvidesStmtMetaModel.getConstructorParameters().add(moduleProvidesStmtMetaModel.withTypesPropertyMetaModel);
-        moduleUsesStmtMetaModel.getConstructorParameters().add(moduleUsesStmtMetaModel.typePropertyMetaModel);
-        moduleOpensStmtMetaModel.getConstructorParameters().add(moduleOpensStmtMetaModel.namePropertyMetaModel);
-        moduleOpensStmtMetaModel.getConstructorParameters().add(moduleOpensStmtMetaModel.moduleNamesPropertyMetaModel);
+        moduleRequiresDirectiveMetaModel.getConstructorParameters().add(moduleRequiresDirectiveMetaModel.modifiersPropertyMetaModel);
+        moduleRequiresDirectiveMetaModel.getConstructorParameters().add(moduleRequiresDirectiveMetaModel.namePropertyMetaModel);
+        moduleExportsDirectiveMetaModel.getConstructorParameters().add(moduleExportsDirectiveMetaModel.namePropertyMetaModel);
+        moduleExportsDirectiveMetaModel.getConstructorParameters().add(moduleExportsDirectiveMetaModel.moduleNamesPropertyMetaModel);
+        moduleProvidesDirectiveMetaModel.getConstructorParameters().add(moduleProvidesDirectiveMetaModel.namePropertyMetaModel);
+        moduleProvidesDirectiveMetaModel.getConstructorParameters().add(moduleProvidesDirectiveMetaModel.withPropertyMetaModel);
+        moduleUsesDirectiveMetaModel.getConstructorParameters().add(moduleUsesDirectiveMetaModel.namePropertyMetaModel);
+        moduleOpensDirectiveMetaModel.getConstructorParameters().add(moduleOpensDirectiveMetaModel.namePropertyMetaModel);
+        moduleOpensDirectiveMetaModel.getConstructorParameters().add(moduleOpensDirectiveMetaModel.moduleNamesPropertyMetaModel);
     }
 
     public static List<BaseNodeMetaModel> getNodeMetaModels() {
@@ -290,8 +289,8 @@
         nodeMetaModels.add(expressionStmtMetaModel);
         nodeMetaModels.add(fieldAccessExprMetaModel);
         nodeMetaModels.add(fieldDeclarationMetaModel);
+        nodeMetaModels.add(forEachStmtMetaModel);
         nodeMetaModels.add(forStmtMetaModel);
-        nodeMetaModels.add(foreachStmtMetaModel);
         nodeMetaModels.add(ifStmtMetaModel);
         nodeMetaModels.add(importDeclarationMetaModel);
         nodeMetaModels.add(initializerDeclarationMetaModel);
@@ -311,13 +310,14 @@
         nodeMetaModels.add(methodCallExprMetaModel);
         nodeMetaModels.add(methodDeclarationMetaModel);
         nodeMetaModels.add(methodReferenceExprMetaModel);
+        nodeMetaModels.add(modifierMetaModel);
         nodeMetaModels.add(moduleDeclarationMetaModel);
-        nodeMetaModels.add(moduleExportsStmtMetaModel);
-        nodeMetaModels.add(moduleOpensStmtMetaModel);
-        nodeMetaModels.add(moduleProvidesStmtMetaModel);
-        nodeMetaModels.add(moduleRequiresStmtMetaModel);
-        nodeMetaModels.add(moduleStmtMetaModel);
-        nodeMetaModels.add(moduleUsesStmtMetaModel);
+        nodeMetaModels.add(moduleDirectiveMetaModel);
+        nodeMetaModels.add(moduleExportsDirectiveMetaModel);
+        nodeMetaModels.add(moduleOpensDirectiveMetaModel);
+        nodeMetaModels.add(moduleProvidesDirectiveMetaModel);
+        nodeMetaModels.add(moduleRequiresDirectiveMetaModel);
+        nodeMetaModels.add(moduleUsesDirectiveMetaModel);
         nodeMetaModels.add(nameExprMetaModel);
         nodeMetaModels.add(nameMetaModel);
         nodeMetaModels.add(nodeMetaModel);
@@ -335,7 +335,8 @@
         nodeMetaModels.add(statementMetaModel);
         nodeMetaModels.add(stringLiteralExprMetaModel);
         nodeMetaModels.add(superExprMetaModel);
-        nodeMetaModels.add(switchEntryStmtMetaModel);
+        nodeMetaModels.add(switchEntryMetaModel);
+        nodeMetaModels.add(switchExprMetaModel);
         nodeMetaModels.add(switchStmtMetaModel);
         nodeMetaModels.add(synchronizedStmtMetaModel);
         nodeMetaModels.add(thisExprMetaModel);
@@ -358,403 +359,409 @@
     }
 
     private static void initializePropertyMetaModels() {
-        nodeMetaModel.commentPropertyMetaModel = new PropertyMetaModel(nodeMetaModel, "comment", com.github.javaparser.ast.comments.Comment.class, Optional.of(commentMetaModel), true, false, false, false, false);
+        nodeMetaModel.commentPropertyMetaModel = new PropertyMetaModel(nodeMetaModel, "comment", com.github.javaparser.ast.comments.Comment.class, Optional.of(commentMetaModel), true, false, false, false);
         nodeMetaModel.getDeclaredPropertyMetaModels().add(nodeMetaModel.commentPropertyMetaModel);
-        bodyDeclarationMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(bodyDeclarationMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        bodyDeclarationMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(bodyDeclarationMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         bodyDeclarationMetaModel.getDeclaredPropertyMetaModels().add(bodyDeclarationMetaModel.annotationsPropertyMetaModel);
-        callableDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
+        callableDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.of(modifierMetaModel), false, false, true, false);
         callableDeclarationMetaModel.getDeclaredPropertyMetaModels().add(callableDeclarationMetaModel.modifiersPropertyMetaModel);
-        callableDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        callableDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         callableDeclarationMetaModel.getDeclaredPropertyMetaModels().add(callableDeclarationMetaModel.namePropertyMetaModel);
-        callableDeclarationMetaModel.parametersPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "parameters", com.github.javaparser.ast.body.Parameter.class, Optional.of(parameterMetaModel), false, false, true, false, false);
+        callableDeclarationMetaModel.parametersPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "parameters", com.github.javaparser.ast.body.Parameter.class, Optional.of(parameterMetaModel), false, false, true, false);
         callableDeclarationMetaModel.getDeclaredPropertyMetaModels().add(callableDeclarationMetaModel.parametersPropertyMetaModel);
-        callableDeclarationMetaModel.receiverParameterPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "receiverParameter", com.github.javaparser.ast.body.ReceiverParameter.class, Optional.of(receiverParameterMetaModel), true, false, false, false, false);
+        callableDeclarationMetaModel.receiverParameterPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "receiverParameter", com.github.javaparser.ast.body.ReceiverParameter.class, Optional.of(receiverParameterMetaModel), true, false, false, false);
         callableDeclarationMetaModel.getDeclaredPropertyMetaModels().add(callableDeclarationMetaModel.receiverParameterPropertyMetaModel);
-        callableDeclarationMetaModel.thrownExceptionsPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "thrownExceptions", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, false, true, false, false);
+        callableDeclarationMetaModel.thrownExceptionsPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "thrownExceptions", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, false, true, false);
         callableDeclarationMetaModel.getDeclaredPropertyMetaModels().add(callableDeclarationMetaModel.thrownExceptionsPropertyMetaModel);
-        callableDeclarationMetaModel.typeParametersPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "typeParameters", com.github.javaparser.ast.type.TypeParameter.class, Optional.of(typeParameterMetaModel), false, false, true, false, false);
+        callableDeclarationMetaModel.typeParametersPropertyMetaModel = new PropertyMetaModel(callableDeclarationMetaModel, "typeParameters", com.github.javaparser.ast.type.TypeParameter.class, Optional.of(typeParameterMetaModel), false, false, true, false);
         callableDeclarationMetaModel.getDeclaredPropertyMetaModels().add(callableDeclarationMetaModel.typeParametersPropertyMetaModel);
-        typeMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(typeMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        typeMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(typeMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         typeMetaModel.getDeclaredPropertyMetaModels().add(typeMetaModel.annotationsPropertyMetaModel);
-        annotationExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(annotationExprMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
+        annotationExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(annotationExprMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
         annotationExprMetaModel.getDeclaredPropertyMetaModels().add(annotationExprMetaModel.namePropertyMetaModel);
-        typeDeclarationMetaModel.membersPropertyMetaModel = new PropertyMetaModel(typeDeclarationMetaModel, "members", com.github.javaparser.ast.body.BodyDeclaration.class, Optional.of(bodyDeclarationMetaModel), false, false, true, false, true);
+        typeDeclarationMetaModel.membersPropertyMetaModel = new PropertyMetaModel(typeDeclarationMetaModel, "members", com.github.javaparser.ast.body.BodyDeclaration.class, Optional.of(bodyDeclarationMetaModel), false, false, true, true);
         typeDeclarationMetaModel.getDeclaredPropertyMetaModels().add(typeDeclarationMetaModel.membersPropertyMetaModel);
-        typeDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(typeDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
+        typeDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(typeDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.of(modifierMetaModel), false, false, true, false);
         typeDeclarationMetaModel.getDeclaredPropertyMetaModels().add(typeDeclarationMetaModel.modifiersPropertyMetaModel);
-        typeDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(typeDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        typeDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(typeDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         typeDeclarationMetaModel.getDeclaredPropertyMetaModels().add(typeDeclarationMetaModel.namePropertyMetaModel);
-        literalStringValueExprMetaModel.valuePropertyMetaModel = new PropertyMetaModel(literalStringValueExprMetaModel, "value", java.lang.String.class, Optional.empty(), false, false, false, false, false);
+        literalStringValueExprMetaModel.valuePropertyMetaModel = new PropertyMetaModel(literalStringValueExprMetaModel, "value", java.lang.String.class, Optional.empty(), false, false, false, false);
         literalStringValueExprMetaModel.getDeclaredPropertyMetaModels().add(literalStringValueExprMetaModel.valuePropertyMetaModel);
-        moduleDeclarationMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        moduleDeclarationMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         moduleDeclarationMetaModel.getDeclaredPropertyMetaModels().add(moduleDeclarationMetaModel.annotationsPropertyMetaModel);
-        moduleDeclarationMetaModel.isOpenPropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "isOpen", boolean.class, Optional.empty(), false, false, false, false, false);
+        moduleDeclarationMetaModel.directivesPropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "directives", com.github.javaparser.ast.modules.ModuleDirective.class, Optional.of(moduleDirectiveMetaModel), false, false, true, false);
+        moduleDeclarationMetaModel.getDeclaredPropertyMetaModels().add(moduleDeclarationMetaModel.directivesPropertyMetaModel);
+        moduleDeclarationMetaModel.isOpenPropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "isOpen", boolean.class, Optional.empty(), false, false, false, false);
         moduleDeclarationMetaModel.getDeclaredPropertyMetaModels().add(moduleDeclarationMetaModel.isOpenPropertyMetaModel);
-        moduleDeclarationMetaModel.moduleStmtsPropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "moduleStmts", com.github.javaparser.ast.modules.ModuleStmt.class, Optional.of(moduleStmtMetaModel), false, false, true, false, false);
-        moduleDeclarationMetaModel.getDeclaredPropertyMetaModels().add(moduleDeclarationMetaModel.moduleStmtsPropertyMetaModel);
-        moduleDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
+        moduleDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleDeclarationMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
         moduleDeclarationMetaModel.getDeclaredPropertyMetaModels().add(moduleDeclarationMetaModel.namePropertyMetaModel);
-        arrayCreationLevelMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(arrayCreationLevelMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        arrayCreationLevelMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(arrayCreationLevelMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         arrayCreationLevelMetaModel.getDeclaredPropertyMetaModels().add(arrayCreationLevelMetaModel.annotationsPropertyMetaModel);
-        arrayCreationLevelMetaModel.dimensionPropertyMetaModel = new PropertyMetaModel(arrayCreationLevelMetaModel, "dimension", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        arrayCreationLevelMetaModel.dimensionPropertyMetaModel = new PropertyMetaModel(arrayCreationLevelMetaModel, "dimension", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         arrayCreationLevelMetaModel.getDeclaredPropertyMetaModels().add(arrayCreationLevelMetaModel.dimensionPropertyMetaModel);
-        compilationUnitMetaModel.importsPropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "imports", com.github.javaparser.ast.ImportDeclaration.class, Optional.of(importDeclarationMetaModel), false, false, true, false, false);
+        compilationUnitMetaModel.importsPropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "imports", com.github.javaparser.ast.ImportDeclaration.class, Optional.of(importDeclarationMetaModel), false, false, true, false);
         compilationUnitMetaModel.getDeclaredPropertyMetaModels().add(compilationUnitMetaModel.importsPropertyMetaModel);
-        compilationUnitMetaModel.modulePropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "module", com.github.javaparser.ast.modules.ModuleDeclaration.class, Optional.of(moduleDeclarationMetaModel), true, false, false, false, false);
+        compilationUnitMetaModel.modulePropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "module", com.github.javaparser.ast.modules.ModuleDeclaration.class, Optional.of(moduleDeclarationMetaModel), true, false, false, false);
         compilationUnitMetaModel.getDeclaredPropertyMetaModels().add(compilationUnitMetaModel.modulePropertyMetaModel);
-        compilationUnitMetaModel.packageDeclarationPropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "packageDeclaration", com.github.javaparser.ast.PackageDeclaration.class, Optional.of(packageDeclarationMetaModel), true, false, false, false, false);
+        compilationUnitMetaModel.packageDeclarationPropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "packageDeclaration", com.github.javaparser.ast.PackageDeclaration.class, Optional.of(packageDeclarationMetaModel), true, false, false, false);
         compilationUnitMetaModel.getDeclaredPropertyMetaModels().add(compilationUnitMetaModel.packageDeclarationPropertyMetaModel);
-        compilationUnitMetaModel.typesPropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "types", com.github.javaparser.ast.body.TypeDeclaration.class, Optional.of(typeDeclarationMetaModel), false, false, true, false, true);
+        compilationUnitMetaModel.typesPropertyMetaModel = new PropertyMetaModel(compilationUnitMetaModel, "types", com.github.javaparser.ast.body.TypeDeclaration.class, Optional.of(typeDeclarationMetaModel), false, false, true, true);
         compilationUnitMetaModel.getDeclaredPropertyMetaModels().add(compilationUnitMetaModel.typesPropertyMetaModel);
-        packageDeclarationMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(packageDeclarationMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        packageDeclarationMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(packageDeclarationMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         packageDeclarationMetaModel.getDeclaredPropertyMetaModels().add(packageDeclarationMetaModel.annotationsPropertyMetaModel);
-        packageDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(packageDeclarationMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
+        packageDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(packageDeclarationMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
         packageDeclarationMetaModel.getDeclaredPropertyMetaModels().add(packageDeclarationMetaModel.namePropertyMetaModel);
-        annotationMemberDeclarationMetaModel.defaultValuePropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "defaultValue", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        modifierMetaModel.keywordPropertyMetaModel = new PropertyMetaModel(modifierMetaModel, "keyword", com.github.javaparser.ast.Modifier.Keyword.class, Optional.empty(), false, false, false, false);
+        modifierMetaModel.getDeclaredPropertyMetaModels().add(modifierMetaModel.keywordPropertyMetaModel);
+        annotationMemberDeclarationMetaModel.defaultValuePropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "defaultValue", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         annotationMemberDeclarationMetaModel.getDeclaredPropertyMetaModels().add(annotationMemberDeclarationMetaModel.defaultValuePropertyMetaModel);
-        annotationMemberDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
+        annotationMemberDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.of(modifierMetaModel), false, false, true, false);
         annotationMemberDeclarationMetaModel.getDeclaredPropertyMetaModels().add(annotationMemberDeclarationMetaModel.modifiersPropertyMetaModel);
-        annotationMemberDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        annotationMemberDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         annotationMemberDeclarationMetaModel.getDeclaredPropertyMetaModels().add(annotationMemberDeclarationMetaModel.namePropertyMetaModel);
-        annotationMemberDeclarationMetaModel.typePropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        annotationMemberDeclarationMetaModel.typePropertyMetaModel = new PropertyMetaModel(annotationMemberDeclarationMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         annotationMemberDeclarationMetaModel.getDeclaredPropertyMetaModels().add(annotationMemberDeclarationMetaModel.typePropertyMetaModel);
-        classOrInterfaceDeclarationMetaModel.extendedTypesPropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "extendedTypes", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false, false);
+        classOrInterfaceDeclarationMetaModel.extendedTypesPropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "extendedTypes", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false);
         classOrInterfaceDeclarationMetaModel.getDeclaredPropertyMetaModels().add(classOrInterfaceDeclarationMetaModel.extendedTypesPropertyMetaModel);
-        classOrInterfaceDeclarationMetaModel.implementedTypesPropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "implementedTypes", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false, false);
+        classOrInterfaceDeclarationMetaModel.implementedTypesPropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "implementedTypes", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false);
         classOrInterfaceDeclarationMetaModel.getDeclaredPropertyMetaModels().add(classOrInterfaceDeclarationMetaModel.implementedTypesPropertyMetaModel);
-        classOrInterfaceDeclarationMetaModel.isInterfacePropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "isInterface", boolean.class, Optional.empty(), false, false, false, false, false);
+        classOrInterfaceDeclarationMetaModel.isInterfacePropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "isInterface", boolean.class, Optional.empty(), false, false, false, false);
         classOrInterfaceDeclarationMetaModel.getDeclaredPropertyMetaModels().add(classOrInterfaceDeclarationMetaModel.isInterfacePropertyMetaModel);
-        classOrInterfaceDeclarationMetaModel.typeParametersPropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "typeParameters", com.github.javaparser.ast.type.TypeParameter.class, Optional.of(typeParameterMetaModel), false, false, true, false, false);
+        classOrInterfaceDeclarationMetaModel.typeParametersPropertyMetaModel = new PropertyMetaModel(classOrInterfaceDeclarationMetaModel, "typeParameters", com.github.javaparser.ast.type.TypeParameter.class, Optional.of(typeParameterMetaModel), false, false, true, false);
         classOrInterfaceDeclarationMetaModel.getDeclaredPropertyMetaModels().add(classOrInterfaceDeclarationMetaModel.typeParametersPropertyMetaModel);
-        constructorDeclarationMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(constructorDeclarationMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false, false);
+        constructorDeclarationMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(constructorDeclarationMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false);
         constructorDeclarationMetaModel.getDeclaredPropertyMetaModels().add(constructorDeclarationMetaModel.bodyPropertyMetaModel);
-        enumConstantDeclarationMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(enumConstantDeclarationMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        enumConstantDeclarationMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(enumConstantDeclarationMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         enumConstantDeclarationMetaModel.getDeclaredPropertyMetaModels().add(enumConstantDeclarationMetaModel.argumentsPropertyMetaModel);
-        enumConstantDeclarationMetaModel.classBodyPropertyMetaModel = new PropertyMetaModel(enumConstantDeclarationMetaModel, "classBody", com.github.javaparser.ast.body.BodyDeclaration.class, Optional.of(bodyDeclarationMetaModel), false, false, true, false, true);
+        enumConstantDeclarationMetaModel.classBodyPropertyMetaModel = new PropertyMetaModel(enumConstantDeclarationMetaModel, "classBody", com.github.javaparser.ast.body.BodyDeclaration.class, Optional.of(bodyDeclarationMetaModel), false, false, true, true);
         enumConstantDeclarationMetaModel.getDeclaredPropertyMetaModels().add(enumConstantDeclarationMetaModel.classBodyPropertyMetaModel);
-        enumConstantDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(enumConstantDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        enumConstantDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(enumConstantDeclarationMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         enumConstantDeclarationMetaModel.getDeclaredPropertyMetaModels().add(enumConstantDeclarationMetaModel.namePropertyMetaModel);
-        enumDeclarationMetaModel.entriesPropertyMetaModel = new PropertyMetaModel(enumDeclarationMetaModel, "entries", com.github.javaparser.ast.body.EnumConstantDeclaration.class, Optional.of(enumConstantDeclarationMetaModel), false, false, true, false, false);
+        enumDeclarationMetaModel.entriesPropertyMetaModel = new PropertyMetaModel(enumDeclarationMetaModel, "entries", com.github.javaparser.ast.body.EnumConstantDeclaration.class, Optional.of(enumConstantDeclarationMetaModel), false, false, true, false);
         enumDeclarationMetaModel.getDeclaredPropertyMetaModels().add(enumDeclarationMetaModel.entriesPropertyMetaModel);
-        enumDeclarationMetaModel.implementedTypesPropertyMetaModel = new PropertyMetaModel(enumDeclarationMetaModel, "implementedTypes", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false, false);
+        enumDeclarationMetaModel.implementedTypesPropertyMetaModel = new PropertyMetaModel(enumDeclarationMetaModel, "implementedTypes", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false);
         enumDeclarationMetaModel.getDeclaredPropertyMetaModels().add(enumDeclarationMetaModel.implementedTypesPropertyMetaModel);
-        fieldDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
+        fieldDeclarationMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.of(modifierMetaModel), false, false, true, false);
         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.variablesPropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "variables", com.github.javaparser.ast.body.VariableDeclarator.class, Optional.of(variableDeclaratorMetaModel), false, true, true, false);
         fieldDeclarationMetaModel.getDeclaredPropertyMetaModels().add(fieldDeclarationMetaModel.variablesPropertyMetaModel);
-        fieldDeclarationMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, false, false, false);
+        fieldDeclarationMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(fieldDeclarationMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, 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.bodyPropertyMetaModel = new PropertyMetaModel(initializerDeclarationMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false);
         initializerDeclarationMetaModel.getDeclaredPropertyMetaModels().add(initializerDeclarationMetaModel.bodyPropertyMetaModel);
-        initializerDeclarationMetaModel.isStaticPropertyMetaModel = new PropertyMetaModel(initializerDeclarationMetaModel, "isStatic", boolean.class, Optional.empty(), false, false, false, false, false);
+        initializerDeclarationMetaModel.isStaticPropertyMetaModel = new PropertyMetaModel(initializerDeclarationMetaModel, "isStatic", boolean.class, Optional.empty(), false, false, false, false);
         initializerDeclarationMetaModel.getDeclaredPropertyMetaModels().add(initializerDeclarationMetaModel.isStaticPropertyMetaModel);
-        methodDeclarationMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(methodDeclarationMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), true, false, false, false, false);
+        methodDeclarationMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(methodDeclarationMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), true, false, false, false);
         methodDeclarationMetaModel.getDeclaredPropertyMetaModels().add(methodDeclarationMetaModel.bodyPropertyMetaModel);
-        methodDeclarationMetaModel.typePropertyMetaModel = new PropertyMetaModel(methodDeclarationMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        methodDeclarationMetaModel.typePropertyMetaModel = new PropertyMetaModel(methodDeclarationMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         methodDeclarationMetaModel.getDeclaredPropertyMetaModels().add(methodDeclarationMetaModel.typePropertyMetaModel);
-        parameterMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        parameterMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         parameterMetaModel.getDeclaredPropertyMetaModels().add(parameterMetaModel.annotationsPropertyMetaModel);
-        parameterMetaModel.isVarArgsPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "isVarArgs", boolean.class, Optional.empty(), false, false, false, false, false);
+        parameterMetaModel.isVarArgsPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "isVarArgs", boolean.class, Optional.empty(), false, false, false, false);
         parameterMetaModel.getDeclaredPropertyMetaModels().add(parameterMetaModel.isVarArgsPropertyMetaModel);
-        parameterMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
+        parameterMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.of(modifierMetaModel), false, false, true, false);
         parameterMetaModel.getDeclaredPropertyMetaModels().add(parameterMetaModel.modifiersPropertyMetaModel);
-        parameterMetaModel.namePropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        parameterMetaModel.namePropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         parameterMetaModel.getDeclaredPropertyMetaModels().add(parameterMetaModel.namePropertyMetaModel);
-        parameterMetaModel.typePropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        parameterMetaModel.typePropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         parameterMetaModel.getDeclaredPropertyMetaModels().add(parameterMetaModel.typePropertyMetaModel);
-        parameterMetaModel.varArgsAnnotationsPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "varArgsAnnotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        parameterMetaModel.varArgsAnnotationsPropertyMetaModel = new PropertyMetaModel(parameterMetaModel, "varArgsAnnotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         parameterMetaModel.getDeclaredPropertyMetaModels().add(parameterMetaModel.varArgsAnnotationsPropertyMetaModel);
-        receiverParameterMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(receiverParameterMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        receiverParameterMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(receiverParameterMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         receiverParameterMetaModel.getDeclaredPropertyMetaModels().add(receiverParameterMetaModel.annotationsPropertyMetaModel);
-        receiverParameterMetaModel.namePropertyMetaModel = new PropertyMetaModel(receiverParameterMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
+        receiverParameterMetaModel.namePropertyMetaModel = new PropertyMetaModel(receiverParameterMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
         receiverParameterMetaModel.getDeclaredPropertyMetaModels().add(receiverParameterMetaModel.namePropertyMetaModel);
-        receiverParameterMetaModel.typePropertyMetaModel = new PropertyMetaModel(receiverParameterMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        receiverParameterMetaModel.typePropertyMetaModel = new PropertyMetaModel(receiverParameterMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         receiverParameterMetaModel.getDeclaredPropertyMetaModels().add(receiverParameterMetaModel.typePropertyMetaModel);
-        variableDeclaratorMetaModel.initializerPropertyMetaModel = new PropertyMetaModel(variableDeclaratorMetaModel, "initializer", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, true, false, false, false);
+        variableDeclaratorMetaModel.initializerPropertyMetaModel = new PropertyMetaModel(variableDeclaratorMetaModel, "initializer", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, true, false, false);
         variableDeclaratorMetaModel.getDeclaredPropertyMetaModels().add(variableDeclaratorMetaModel.initializerPropertyMetaModel);
-        variableDeclaratorMetaModel.namePropertyMetaModel = new PropertyMetaModel(variableDeclaratorMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        variableDeclaratorMetaModel.namePropertyMetaModel = new PropertyMetaModel(variableDeclaratorMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         variableDeclaratorMetaModel.getDeclaredPropertyMetaModels().add(variableDeclaratorMetaModel.namePropertyMetaModel);
-        variableDeclaratorMetaModel.typePropertyMetaModel = new PropertyMetaModel(variableDeclaratorMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        variableDeclaratorMetaModel.typePropertyMetaModel = new PropertyMetaModel(variableDeclaratorMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         variableDeclaratorMetaModel.getDeclaredPropertyMetaModels().add(variableDeclaratorMetaModel.typePropertyMetaModel);
-        commentMetaModel.contentPropertyMetaModel = new PropertyMetaModel(commentMetaModel, "content", java.lang.String.class, Optional.empty(), false, false, false, false, false);
+        commentMetaModel.contentPropertyMetaModel = new PropertyMetaModel(commentMetaModel, "content", java.lang.String.class, Optional.empty(), false, false, false, false);
         commentMetaModel.getDeclaredPropertyMetaModels().add(commentMetaModel.contentPropertyMetaModel);
-        arrayAccessExprMetaModel.indexPropertyMetaModel = new PropertyMetaModel(arrayAccessExprMetaModel, "index", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        arrayAccessExprMetaModel.indexPropertyMetaModel = new PropertyMetaModel(arrayAccessExprMetaModel, "index", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         arrayAccessExprMetaModel.getDeclaredPropertyMetaModels().add(arrayAccessExprMetaModel.indexPropertyMetaModel);
-        arrayAccessExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(arrayAccessExprMetaModel, "name", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        arrayAccessExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(arrayAccessExprMetaModel, "name", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         arrayAccessExprMetaModel.getDeclaredPropertyMetaModels().add(arrayAccessExprMetaModel.namePropertyMetaModel);
-        arrayCreationExprMetaModel.elementTypePropertyMetaModel = new PropertyMetaModel(arrayCreationExprMetaModel, "elementType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        arrayCreationExprMetaModel.elementTypePropertyMetaModel = new PropertyMetaModel(arrayCreationExprMetaModel, "elementType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         arrayCreationExprMetaModel.getDeclaredPropertyMetaModels().add(arrayCreationExprMetaModel.elementTypePropertyMetaModel);
-        arrayCreationExprMetaModel.initializerPropertyMetaModel = new PropertyMetaModel(arrayCreationExprMetaModel, "initializer", com.github.javaparser.ast.expr.ArrayInitializerExpr.class, Optional.of(arrayInitializerExprMetaModel), true, false, false, false, false);
+        arrayCreationExprMetaModel.initializerPropertyMetaModel = new PropertyMetaModel(arrayCreationExprMetaModel, "initializer", com.github.javaparser.ast.expr.ArrayInitializerExpr.class, Optional.of(arrayInitializerExprMetaModel), true, false, false, false);
         arrayCreationExprMetaModel.getDeclaredPropertyMetaModels().add(arrayCreationExprMetaModel.initializerPropertyMetaModel);
-        arrayCreationExprMetaModel.levelsPropertyMetaModel = new PropertyMetaModel(arrayCreationExprMetaModel, "levels", com.github.javaparser.ast.ArrayCreationLevel.class, Optional.of(arrayCreationLevelMetaModel), false, true, true, false, false);
+        arrayCreationExprMetaModel.levelsPropertyMetaModel = new PropertyMetaModel(arrayCreationExprMetaModel, "levels", com.github.javaparser.ast.ArrayCreationLevel.class, Optional.of(arrayCreationLevelMetaModel), false, true, true, false);
         arrayCreationExprMetaModel.getDeclaredPropertyMetaModels().add(arrayCreationExprMetaModel.levelsPropertyMetaModel);
-        arrayInitializerExprMetaModel.valuesPropertyMetaModel = new PropertyMetaModel(arrayInitializerExprMetaModel, "values", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        arrayInitializerExprMetaModel.valuesPropertyMetaModel = new PropertyMetaModel(arrayInitializerExprMetaModel, "values", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         arrayInitializerExprMetaModel.getDeclaredPropertyMetaModels().add(arrayInitializerExprMetaModel.valuesPropertyMetaModel);
-        assignExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(assignExprMetaModel, "operator", com.github.javaparser.ast.expr.AssignExpr.Operator.class, Optional.empty(), false, false, false, false, false);
+        assignExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(assignExprMetaModel, "operator", com.github.javaparser.ast.expr.AssignExpr.Operator.class, Optional.empty(), false, false, false, false);
         assignExprMetaModel.getDeclaredPropertyMetaModels().add(assignExprMetaModel.operatorPropertyMetaModel);
-        assignExprMetaModel.targetPropertyMetaModel = new PropertyMetaModel(assignExprMetaModel, "target", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        assignExprMetaModel.targetPropertyMetaModel = new PropertyMetaModel(assignExprMetaModel, "target", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         assignExprMetaModel.getDeclaredPropertyMetaModels().add(assignExprMetaModel.targetPropertyMetaModel);
-        assignExprMetaModel.valuePropertyMetaModel = new PropertyMetaModel(assignExprMetaModel, "value", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        assignExprMetaModel.valuePropertyMetaModel = new PropertyMetaModel(assignExprMetaModel, "value", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         assignExprMetaModel.getDeclaredPropertyMetaModels().add(assignExprMetaModel.valuePropertyMetaModel);
-        binaryExprMetaModel.leftPropertyMetaModel = new PropertyMetaModel(binaryExprMetaModel, "left", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        binaryExprMetaModel.leftPropertyMetaModel = new PropertyMetaModel(binaryExprMetaModel, "left", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         binaryExprMetaModel.getDeclaredPropertyMetaModels().add(binaryExprMetaModel.leftPropertyMetaModel);
-        binaryExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(binaryExprMetaModel, "operator", com.github.javaparser.ast.expr.BinaryExpr.Operator.class, Optional.empty(), false, false, false, false, false);
+        binaryExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(binaryExprMetaModel, "operator", com.github.javaparser.ast.expr.BinaryExpr.Operator.class, Optional.empty(), false, false, false, false);
         binaryExprMetaModel.getDeclaredPropertyMetaModels().add(binaryExprMetaModel.operatorPropertyMetaModel);
-        binaryExprMetaModel.rightPropertyMetaModel = new PropertyMetaModel(binaryExprMetaModel, "right", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        binaryExprMetaModel.rightPropertyMetaModel = new PropertyMetaModel(binaryExprMetaModel, "right", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         binaryExprMetaModel.getDeclaredPropertyMetaModels().add(binaryExprMetaModel.rightPropertyMetaModel);
-        booleanLiteralExprMetaModel.valuePropertyMetaModel = new PropertyMetaModel(booleanLiteralExprMetaModel, "value", boolean.class, Optional.empty(), false, false, false, false, false);
+        booleanLiteralExprMetaModel.valuePropertyMetaModel = new PropertyMetaModel(booleanLiteralExprMetaModel, "value", boolean.class, Optional.empty(), false, false, false, false);
         booleanLiteralExprMetaModel.getDeclaredPropertyMetaModels().add(booleanLiteralExprMetaModel.valuePropertyMetaModel);
-        castExprMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(castExprMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        castExprMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(castExprMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         castExprMetaModel.getDeclaredPropertyMetaModels().add(castExprMetaModel.expressionPropertyMetaModel);
-        castExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(castExprMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        castExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(castExprMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         castExprMetaModel.getDeclaredPropertyMetaModels().add(castExprMetaModel.typePropertyMetaModel);
-        classExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(classExprMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        classExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(classExprMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         classExprMetaModel.getDeclaredPropertyMetaModels().add(classExprMetaModel.typePropertyMetaModel);
-        conditionalExprMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(conditionalExprMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        conditionalExprMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(conditionalExprMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         conditionalExprMetaModel.getDeclaredPropertyMetaModels().add(conditionalExprMetaModel.conditionPropertyMetaModel);
-        conditionalExprMetaModel.elseExprPropertyMetaModel = new PropertyMetaModel(conditionalExprMetaModel, "elseExpr", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        conditionalExprMetaModel.elseExprPropertyMetaModel = new PropertyMetaModel(conditionalExprMetaModel, "elseExpr", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         conditionalExprMetaModel.getDeclaredPropertyMetaModels().add(conditionalExprMetaModel.elseExprPropertyMetaModel);
-        conditionalExprMetaModel.thenExprPropertyMetaModel = new PropertyMetaModel(conditionalExprMetaModel, "thenExpr", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        conditionalExprMetaModel.thenExprPropertyMetaModel = new PropertyMetaModel(conditionalExprMetaModel, "thenExpr", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         conditionalExprMetaModel.getDeclaredPropertyMetaModels().add(conditionalExprMetaModel.thenExprPropertyMetaModel);
-        enclosedExprMetaModel.innerPropertyMetaModel = new PropertyMetaModel(enclosedExprMetaModel, "inner", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        enclosedExprMetaModel.innerPropertyMetaModel = new PropertyMetaModel(enclosedExprMetaModel, "inner", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         enclosedExprMetaModel.getDeclaredPropertyMetaModels().add(enclosedExprMetaModel.innerPropertyMetaModel);
-        fieldAccessExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        fieldAccessExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         fieldAccessExprMetaModel.getDeclaredPropertyMetaModels().add(fieldAccessExprMetaModel.namePropertyMetaModel);
-        fieldAccessExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        fieldAccessExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         fieldAccessExprMetaModel.getDeclaredPropertyMetaModels().add(fieldAccessExprMetaModel.scopePropertyMetaModel);
-        fieldAccessExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false, false);
+        fieldAccessExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false);
         fieldAccessExprMetaModel.getDeclaredPropertyMetaModels().add(fieldAccessExprMetaModel.typeArgumentsPropertyMetaModel);
-        fieldAccessExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false, false);
+        fieldAccessExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(fieldAccessExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false);
         fieldAccessExprMetaModel.getDerivedPropertyMetaModels().add(fieldAccessExprMetaModel.usingDiamondOperatorPropertyMetaModel);
-        instanceOfExprMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(instanceOfExprMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        instanceOfExprMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(instanceOfExprMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         instanceOfExprMetaModel.getDeclaredPropertyMetaModels().add(instanceOfExprMetaModel.expressionPropertyMetaModel);
-        instanceOfExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(instanceOfExprMetaModel, "type", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, false, false, false, false);
+        instanceOfExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(instanceOfExprMetaModel, "type", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, false, false, false);
         instanceOfExprMetaModel.getDeclaredPropertyMetaModels().add(instanceOfExprMetaModel.typePropertyMetaModel);
-        lambdaExprMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false, false);
+        lambdaExprMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false);
         lambdaExprMetaModel.getDeclaredPropertyMetaModels().add(lambdaExprMetaModel.bodyPropertyMetaModel);
-        lambdaExprMetaModel.isEnclosingParametersPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "isEnclosingParameters", boolean.class, Optional.empty(), false, false, false, false, false);
+        lambdaExprMetaModel.isEnclosingParametersPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "isEnclosingParameters", boolean.class, Optional.empty(), false, false, false, false);
         lambdaExprMetaModel.getDeclaredPropertyMetaModels().add(lambdaExprMetaModel.isEnclosingParametersPropertyMetaModel);
-        lambdaExprMetaModel.parametersPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "parameters", com.github.javaparser.ast.body.Parameter.class, Optional.of(parameterMetaModel), false, false, true, false, false);
+        lambdaExprMetaModel.parametersPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "parameters", com.github.javaparser.ast.body.Parameter.class, Optional.of(parameterMetaModel), false, false, true, false);
         lambdaExprMetaModel.getDeclaredPropertyMetaModels().add(lambdaExprMetaModel.parametersPropertyMetaModel);
-        lambdaExprMetaModel.expressionBodyPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "expressionBody", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        lambdaExprMetaModel.expressionBodyPropertyMetaModel = new PropertyMetaModel(lambdaExprMetaModel, "expressionBody", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         lambdaExprMetaModel.getDerivedPropertyMetaModels().add(lambdaExprMetaModel.expressionBodyPropertyMetaModel);
-        memberValuePairMetaModel.namePropertyMetaModel = new PropertyMetaModel(memberValuePairMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        memberValuePairMetaModel.namePropertyMetaModel = new PropertyMetaModel(memberValuePairMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         memberValuePairMetaModel.getDeclaredPropertyMetaModels().add(memberValuePairMetaModel.namePropertyMetaModel);
-        memberValuePairMetaModel.valuePropertyMetaModel = new PropertyMetaModel(memberValuePairMetaModel, "value", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        memberValuePairMetaModel.valuePropertyMetaModel = new PropertyMetaModel(memberValuePairMetaModel, "value", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         memberValuePairMetaModel.getDeclaredPropertyMetaModels().add(memberValuePairMetaModel.valuePropertyMetaModel);
-        methodCallExprMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        methodCallExprMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         methodCallExprMetaModel.getDeclaredPropertyMetaModels().add(methodCallExprMetaModel.argumentsPropertyMetaModel);
-        methodCallExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        methodCallExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         methodCallExprMetaModel.getDeclaredPropertyMetaModels().add(methodCallExprMetaModel.namePropertyMetaModel);
-        methodCallExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        methodCallExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         methodCallExprMetaModel.getDeclaredPropertyMetaModels().add(methodCallExprMetaModel.scopePropertyMetaModel);
-        methodCallExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false, false);
+        methodCallExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false);
         methodCallExprMetaModel.getDeclaredPropertyMetaModels().add(methodCallExprMetaModel.typeArgumentsPropertyMetaModel);
-        methodCallExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false, false);
+        methodCallExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(methodCallExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false);
         methodCallExprMetaModel.getDerivedPropertyMetaModels().add(methodCallExprMetaModel.usingDiamondOperatorPropertyMetaModel);
-        methodReferenceExprMetaModel.identifierPropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "identifier", java.lang.String.class, Optional.empty(), false, true, false, false, false);
+        methodReferenceExprMetaModel.identifierPropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "identifier", java.lang.String.class, Optional.empty(), false, true, false, false);
         methodReferenceExprMetaModel.getDeclaredPropertyMetaModels().add(methodReferenceExprMetaModel.identifierPropertyMetaModel);
-        methodReferenceExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        methodReferenceExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         methodReferenceExprMetaModel.getDeclaredPropertyMetaModels().add(methodReferenceExprMetaModel.scopePropertyMetaModel);
-        methodReferenceExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false, false);
+        methodReferenceExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false);
         methodReferenceExprMetaModel.getDeclaredPropertyMetaModels().add(methodReferenceExprMetaModel.typeArgumentsPropertyMetaModel);
-        methodReferenceExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false, false);
+        methodReferenceExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(methodReferenceExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false);
         methodReferenceExprMetaModel.getDerivedPropertyMetaModels().add(methodReferenceExprMetaModel.usingDiamondOperatorPropertyMetaModel);
-        nameExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(nameExprMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        nameExprMetaModel.namePropertyMetaModel = new PropertyMetaModel(nameExprMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         nameExprMetaModel.getDeclaredPropertyMetaModels().add(nameExprMetaModel.namePropertyMetaModel);
-        nameMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(nameMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
-        nameMetaModel.getDeclaredPropertyMetaModels().add(nameMetaModel.annotationsPropertyMetaModel);
-        nameMetaModel.identifierPropertyMetaModel = new PropertyMetaModel(nameMetaModel, "identifier", java.lang.String.class, Optional.empty(), false, true, false, false, false);
+        nameMetaModel.identifierPropertyMetaModel = new PropertyMetaModel(nameMetaModel, "identifier", java.lang.String.class, Optional.empty(), false, true, false, false);
         nameMetaModel.getDeclaredPropertyMetaModels().add(nameMetaModel.identifierPropertyMetaModel);
-        nameMetaModel.qualifierPropertyMetaModel = new PropertyMetaModel(nameMetaModel, "qualifier", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), true, false, false, false, false);
+        nameMetaModel.qualifierPropertyMetaModel = new PropertyMetaModel(nameMetaModel, "qualifier", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), true, false, false, false);
         nameMetaModel.getDeclaredPropertyMetaModels().add(nameMetaModel.qualifierPropertyMetaModel);
-        normalAnnotationExprMetaModel.pairsPropertyMetaModel = new PropertyMetaModel(normalAnnotationExprMetaModel, "pairs", com.github.javaparser.ast.expr.MemberValuePair.class, Optional.of(memberValuePairMetaModel), false, false, true, false, false);
+        normalAnnotationExprMetaModel.pairsPropertyMetaModel = new PropertyMetaModel(normalAnnotationExprMetaModel, "pairs", com.github.javaparser.ast.expr.MemberValuePair.class, Optional.of(memberValuePairMetaModel), false, false, true, false);
         normalAnnotationExprMetaModel.getDeclaredPropertyMetaModels().add(normalAnnotationExprMetaModel.pairsPropertyMetaModel);
-        objectCreationExprMetaModel.anonymousClassBodyPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "anonymousClassBody", com.github.javaparser.ast.body.BodyDeclaration.class, Optional.of(bodyDeclarationMetaModel), true, false, true, false, true);
+        objectCreationExprMetaModel.anonymousClassBodyPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "anonymousClassBody", com.github.javaparser.ast.body.BodyDeclaration.class, Optional.of(bodyDeclarationMetaModel), true, false, true, true);
         objectCreationExprMetaModel.getDeclaredPropertyMetaModels().add(objectCreationExprMetaModel.anonymousClassBodyPropertyMetaModel);
-        objectCreationExprMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        objectCreationExprMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         objectCreationExprMetaModel.getDeclaredPropertyMetaModels().add(objectCreationExprMetaModel.argumentsPropertyMetaModel);
-        objectCreationExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        objectCreationExprMetaModel.scopePropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "scope", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         objectCreationExprMetaModel.getDeclaredPropertyMetaModels().add(objectCreationExprMetaModel.scopePropertyMetaModel);
-        objectCreationExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "type", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, false, false, false);
+        objectCreationExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "type", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, false, false);
         objectCreationExprMetaModel.getDeclaredPropertyMetaModels().add(objectCreationExprMetaModel.typePropertyMetaModel);
-        objectCreationExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false, false);
+        objectCreationExprMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false);
         objectCreationExprMetaModel.getDeclaredPropertyMetaModels().add(objectCreationExprMetaModel.typeArgumentsPropertyMetaModel);
-        objectCreationExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false, false);
+        objectCreationExprMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(objectCreationExprMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false);
         objectCreationExprMetaModel.getDerivedPropertyMetaModels().add(objectCreationExprMetaModel.usingDiamondOperatorPropertyMetaModel);
-        simpleNameMetaModel.identifierPropertyMetaModel = new PropertyMetaModel(simpleNameMetaModel, "identifier", java.lang.String.class, Optional.empty(), false, true, false, false, false);
+        simpleNameMetaModel.identifierPropertyMetaModel = new PropertyMetaModel(simpleNameMetaModel, "identifier", java.lang.String.class, Optional.empty(), false, true, false, false);
         simpleNameMetaModel.getDeclaredPropertyMetaModels().add(simpleNameMetaModel.identifierPropertyMetaModel);
-        singleMemberAnnotationExprMetaModel.memberValuePropertyMetaModel = new PropertyMetaModel(singleMemberAnnotationExprMetaModel, "memberValue", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        singleMemberAnnotationExprMetaModel.memberValuePropertyMetaModel = new PropertyMetaModel(singleMemberAnnotationExprMetaModel, "memberValue", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         singleMemberAnnotationExprMetaModel.getDeclaredPropertyMetaModels().add(singleMemberAnnotationExprMetaModel.memberValuePropertyMetaModel);
-        superExprMetaModel.classExprPropertyMetaModel = new PropertyMetaModel(superExprMetaModel, "classExpr", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
-        superExprMetaModel.getDeclaredPropertyMetaModels().add(superExprMetaModel.classExprPropertyMetaModel);
-        thisExprMetaModel.classExprPropertyMetaModel = new PropertyMetaModel(thisExprMetaModel, "classExpr", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
-        thisExprMetaModel.getDeclaredPropertyMetaModels().add(thisExprMetaModel.classExprPropertyMetaModel);
-        typeExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(typeExprMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        superExprMetaModel.typeNamePropertyMetaModel = new PropertyMetaModel(superExprMetaModel, "typeName", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), true, false, false, false);
+        superExprMetaModel.getDeclaredPropertyMetaModels().add(superExprMetaModel.typeNamePropertyMetaModel);
+        thisExprMetaModel.typeNamePropertyMetaModel = new PropertyMetaModel(thisExprMetaModel, "typeName", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), true, false, false, false);
+        thisExprMetaModel.getDeclaredPropertyMetaModels().add(thisExprMetaModel.typeNamePropertyMetaModel);
+        typeExprMetaModel.typePropertyMetaModel = new PropertyMetaModel(typeExprMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         typeExprMetaModel.getDeclaredPropertyMetaModels().add(typeExprMetaModel.typePropertyMetaModel);
-        unaryExprMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        unaryExprMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         unaryExprMetaModel.getDeclaredPropertyMetaModels().add(unaryExprMetaModel.expressionPropertyMetaModel);
-        unaryExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "operator", com.github.javaparser.ast.expr.UnaryExpr.Operator.class, Optional.empty(), false, false, false, false, false);
+        unaryExprMetaModel.operatorPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "operator", com.github.javaparser.ast.expr.UnaryExpr.Operator.class, Optional.empty(), false, false, false, false);
         unaryExprMetaModel.getDeclaredPropertyMetaModels().add(unaryExprMetaModel.operatorPropertyMetaModel);
-        unaryExprMetaModel.postfixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "postfix", boolean.class, Optional.empty(), false, false, false, false, false);
+        unaryExprMetaModel.postfixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "postfix", boolean.class, Optional.empty(), false, false, false, false);
         unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.postfixPropertyMetaModel);
-        unaryExprMetaModel.prefixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "prefix", boolean.class, Optional.empty(), false, false, false, false, false);
+        unaryExprMetaModel.prefixPropertyMetaModel = new PropertyMetaModel(unaryExprMetaModel, "prefix", boolean.class, Optional.empty(), false, false, false, false);
         unaryExprMetaModel.getDerivedPropertyMetaModels().add(unaryExprMetaModel.prefixPropertyMetaModel);
-        variableDeclarationExprMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false, false);
+        variableDeclarationExprMetaModel.annotationsPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "annotations", com.github.javaparser.ast.expr.AnnotationExpr.class, Optional.of(annotationExprMetaModel), false, false, true, false);
         variableDeclarationExprMetaModel.getDeclaredPropertyMetaModels().add(variableDeclarationExprMetaModel.annotationsPropertyMetaModel);
-        variableDeclarationExprMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
+        variableDeclarationExprMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.of(modifierMetaModel), false, false, true, false);
         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.variablesPropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "variables", com.github.javaparser.ast.body.VariableDeclarator.class, Optional.of(variableDeclaratorMetaModel), false, true, true, false);
         variableDeclarationExprMetaModel.getDeclaredPropertyMetaModels().add(variableDeclarationExprMetaModel.variablesPropertyMetaModel);
-        variableDeclarationExprMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, false, false, false);
+        variableDeclarationExprMetaModel.maximumCommonTypePropertyMetaModel = new PropertyMetaModel(variableDeclarationExprMetaModel, "maximumCommonType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, false, false);
         variableDeclarationExprMetaModel.getDerivedPropertyMetaModels().add(variableDeclarationExprMetaModel.maximumCommonTypePropertyMetaModel);
-        importDeclarationMetaModel.isAsteriskPropertyMetaModel = new PropertyMetaModel(importDeclarationMetaModel, "isAsterisk", boolean.class, Optional.empty(), false, false, false, false, false);
+        switchExprMetaModel.entriesPropertyMetaModel = new PropertyMetaModel(switchExprMetaModel, "entries", com.github.javaparser.ast.stmt.SwitchEntry.class, Optional.of(switchEntryMetaModel), false, false, true, false);
+        switchExprMetaModel.getDeclaredPropertyMetaModels().add(switchExprMetaModel.entriesPropertyMetaModel);
+        switchExprMetaModel.selectorPropertyMetaModel = new PropertyMetaModel(switchExprMetaModel, "selector", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
+        switchExprMetaModel.getDeclaredPropertyMetaModels().add(switchExprMetaModel.selectorPropertyMetaModel);
+        importDeclarationMetaModel.isAsteriskPropertyMetaModel = new PropertyMetaModel(importDeclarationMetaModel, "isAsterisk", boolean.class, Optional.empty(), false, false, false, false);
         importDeclarationMetaModel.getDeclaredPropertyMetaModels().add(importDeclarationMetaModel.isAsteriskPropertyMetaModel);
-        importDeclarationMetaModel.isStaticPropertyMetaModel = new PropertyMetaModel(importDeclarationMetaModel, "isStatic", boolean.class, Optional.empty(), false, false, false, false, false);
+        importDeclarationMetaModel.isStaticPropertyMetaModel = new PropertyMetaModel(importDeclarationMetaModel, "isStatic", boolean.class, Optional.empty(), false, false, false, false);
         importDeclarationMetaModel.getDeclaredPropertyMetaModels().add(importDeclarationMetaModel.isStaticPropertyMetaModel);
-        importDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(importDeclarationMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
+        importDeclarationMetaModel.namePropertyMetaModel = new PropertyMetaModel(importDeclarationMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
         importDeclarationMetaModel.getDeclaredPropertyMetaModels().add(importDeclarationMetaModel.namePropertyMetaModel);
-        assertStmtMetaModel.checkPropertyMetaModel = new PropertyMetaModel(assertStmtMetaModel, "check", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        assertStmtMetaModel.checkPropertyMetaModel = new PropertyMetaModel(assertStmtMetaModel, "check", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         assertStmtMetaModel.getDeclaredPropertyMetaModels().add(assertStmtMetaModel.checkPropertyMetaModel);
-        assertStmtMetaModel.messagePropertyMetaModel = new PropertyMetaModel(assertStmtMetaModel, "message", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        assertStmtMetaModel.messagePropertyMetaModel = new PropertyMetaModel(assertStmtMetaModel, "message", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         assertStmtMetaModel.getDeclaredPropertyMetaModels().add(assertStmtMetaModel.messagePropertyMetaModel);
-        blockStmtMetaModel.statementsPropertyMetaModel = new PropertyMetaModel(blockStmtMetaModel, "statements", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, true, false, false);
+        blockStmtMetaModel.statementsPropertyMetaModel = new PropertyMetaModel(blockStmtMetaModel, "statements", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, true, false);
         blockStmtMetaModel.getDeclaredPropertyMetaModels().add(blockStmtMetaModel.statementsPropertyMetaModel);
-        breakStmtMetaModel.labelPropertyMetaModel = new PropertyMetaModel(breakStmtMetaModel, "label", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), true, false, false, false, false);
-        breakStmtMetaModel.getDeclaredPropertyMetaModels().add(breakStmtMetaModel.labelPropertyMetaModel);
-        catchClauseMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(catchClauseMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false, false);
+        breakStmtMetaModel.valuePropertyMetaModel = new PropertyMetaModel(breakStmtMetaModel, "value", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
+        breakStmtMetaModel.getDeclaredPropertyMetaModels().add(breakStmtMetaModel.valuePropertyMetaModel);
+        catchClauseMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(catchClauseMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false);
         catchClauseMetaModel.getDeclaredPropertyMetaModels().add(catchClauseMetaModel.bodyPropertyMetaModel);
-        catchClauseMetaModel.parameterPropertyMetaModel = new PropertyMetaModel(catchClauseMetaModel, "parameter", com.github.javaparser.ast.body.Parameter.class, Optional.of(parameterMetaModel), false, false, false, false, false);
+        catchClauseMetaModel.parameterPropertyMetaModel = new PropertyMetaModel(catchClauseMetaModel, "parameter", com.github.javaparser.ast.body.Parameter.class, Optional.of(parameterMetaModel), false, false, false, false);
         catchClauseMetaModel.getDeclaredPropertyMetaModels().add(catchClauseMetaModel.parameterPropertyMetaModel);
-        continueStmtMetaModel.labelPropertyMetaModel = new PropertyMetaModel(continueStmtMetaModel, "label", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), true, false, false, false, false);
+        continueStmtMetaModel.labelPropertyMetaModel = new PropertyMetaModel(continueStmtMetaModel, "label", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), true, false, false, false);
         continueStmtMetaModel.getDeclaredPropertyMetaModels().add(continueStmtMetaModel.labelPropertyMetaModel);
-        doStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(doStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false, false);
+        doStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(doStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false);
         doStmtMetaModel.getDeclaredPropertyMetaModels().add(doStmtMetaModel.bodyPropertyMetaModel);
-        doStmtMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(doStmtMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        doStmtMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(doStmtMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         doStmtMetaModel.getDeclaredPropertyMetaModels().add(doStmtMetaModel.conditionPropertyMetaModel);
-        explicitConstructorInvocationStmtMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        explicitConstructorInvocationStmtMetaModel.argumentsPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "arguments", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         explicitConstructorInvocationStmtMetaModel.getDeclaredPropertyMetaModels().add(explicitConstructorInvocationStmtMetaModel.argumentsPropertyMetaModel);
-        explicitConstructorInvocationStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        explicitConstructorInvocationStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         explicitConstructorInvocationStmtMetaModel.getDeclaredPropertyMetaModels().add(explicitConstructorInvocationStmtMetaModel.expressionPropertyMetaModel);
-        explicitConstructorInvocationStmtMetaModel.isThisPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "isThis", boolean.class, Optional.empty(), false, false, false, false, false);
+        explicitConstructorInvocationStmtMetaModel.isThisPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "isThis", boolean.class, Optional.empty(), false, false, false, false);
         explicitConstructorInvocationStmtMetaModel.getDeclaredPropertyMetaModels().add(explicitConstructorInvocationStmtMetaModel.isThisPropertyMetaModel);
-        explicitConstructorInvocationStmtMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false, false);
+        explicitConstructorInvocationStmtMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false);
         explicitConstructorInvocationStmtMetaModel.getDeclaredPropertyMetaModels().add(explicitConstructorInvocationStmtMetaModel.typeArgumentsPropertyMetaModel);
-        explicitConstructorInvocationStmtMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false, false);
+        explicitConstructorInvocationStmtMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(explicitConstructorInvocationStmtMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false);
         explicitConstructorInvocationStmtMetaModel.getDerivedPropertyMetaModels().add(explicitConstructorInvocationStmtMetaModel.usingDiamondOperatorPropertyMetaModel);
-        expressionStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(expressionStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        expressionStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(expressionStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         expressionStmtMetaModel.getDeclaredPropertyMetaModels().add(expressionStmtMetaModel.expressionPropertyMetaModel);
-        foreachStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(foreachStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false, false);
-        foreachStmtMetaModel.getDeclaredPropertyMetaModels().add(foreachStmtMetaModel.bodyPropertyMetaModel);
-        foreachStmtMetaModel.iterablePropertyMetaModel = new PropertyMetaModel(foreachStmtMetaModel, "iterable", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
-        foreachStmtMetaModel.getDeclaredPropertyMetaModels().add(foreachStmtMetaModel.iterablePropertyMetaModel);
-        foreachStmtMetaModel.variablePropertyMetaModel = new PropertyMetaModel(foreachStmtMetaModel, "variable", com.github.javaparser.ast.expr.VariableDeclarationExpr.class, Optional.of(variableDeclarationExprMetaModel), false, false, false, false, false);
-        foreachStmtMetaModel.getDeclaredPropertyMetaModels().add(foreachStmtMetaModel.variablePropertyMetaModel);
-        forStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false, false);
+        forEachStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(forEachStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false);
+        forEachStmtMetaModel.getDeclaredPropertyMetaModels().add(forEachStmtMetaModel.bodyPropertyMetaModel);
+        forEachStmtMetaModel.iterablePropertyMetaModel = new PropertyMetaModel(forEachStmtMetaModel, "iterable", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
+        forEachStmtMetaModel.getDeclaredPropertyMetaModels().add(forEachStmtMetaModel.iterablePropertyMetaModel);
+        forEachStmtMetaModel.variablePropertyMetaModel = new PropertyMetaModel(forEachStmtMetaModel, "variable", com.github.javaparser.ast.expr.VariableDeclarationExpr.class, Optional.of(variableDeclarationExprMetaModel), false, false, false, false);
+        forEachStmtMetaModel.getDeclaredPropertyMetaModels().add(forEachStmtMetaModel.variablePropertyMetaModel);
+        forStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false);
         forStmtMetaModel.getDeclaredPropertyMetaModels().add(forStmtMetaModel.bodyPropertyMetaModel);
-        forStmtMetaModel.comparePropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "compare", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        forStmtMetaModel.comparePropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "compare", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         forStmtMetaModel.getDeclaredPropertyMetaModels().add(forStmtMetaModel.comparePropertyMetaModel);
-        forStmtMetaModel.initializationPropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "initialization", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        forStmtMetaModel.initializationPropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "initialization", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         forStmtMetaModel.getDeclaredPropertyMetaModels().add(forStmtMetaModel.initializationPropertyMetaModel);
-        forStmtMetaModel.updatePropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "update", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        forStmtMetaModel.updatePropertyMetaModel = new PropertyMetaModel(forStmtMetaModel, "update", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         forStmtMetaModel.getDeclaredPropertyMetaModels().add(forStmtMetaModel.updatePropertyMetaModel);
-        ifStmtMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        ifStmtMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         ifStmtMetaModel.getDeclaredPropertyMetaModels().add(ifStmtMetaModel.conditionPropertyMetaModel);
-        ifStmtMetaModel.elseStmtPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "elseStmt", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), true, false, false, false, false);
+        ifStmtMetaModel.elseStmtPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "elseStmt", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), true, false, false, false);
         ifStmtMetaModel.getDeclaredPropertyMetaModels().add(ifStmtMetaModel.elseStmtPropertyMetaModel);
-        ifStmtMetaModel.thenStmtPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "thenStmt", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false, false);
+        ifStmtMetaModel.thenStmtPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "thenStmt", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false);
         ifStmtMetaModel.getDeclaredPropertyMetaModels().add(ifStmtMetaModel.thenStmtPropertyMetaModel);
-        ifStmtMetaModel.cascadingIfStmtPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "cascadingIfStmt", boolean.class, Optional.empty(), false, false, false, false, false);
+        ifStmtMetaModel.cascadingIfStmtPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "cascadingIfStmt", boolean.class, Optional.empty(), false, false, false, false);
         ifStmtMetaModel.getDerivedPropertyMetaModels().add(ifStmtMetaModel.cascadingIfStmtPropertyMetaModel);
-        ifStmtMetaModel.elseBlockPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "elseBlock", boolean.class, Optional.empty(), false, false, false, false, false);
+        ifStmtMetaModel.elseBlockPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "elseBlock", boolean.class, Optional.empty(), false, false, false, false);
         ifStmtMetaModel.getDerivedPropertyMetaModels().add(ifStmtMetaModel.elseBlockPropertyMetaModel);
-        ifStmtMetaModel.elseBranchPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "elseBranch", boolean.class, Optional.empty(), false, false, false, false, false);
+        ifStmtMetaModel.elseBranchPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "elseBranch", boolean.class, Optional.empty(), false, false, false, false);
         ifStmtMetaModel.getDerivedPropertyMetaModels().add(ifStmtMetaModel.elseBranchPropertyMetaModel);
-        ifStmtMetaModel.thenBlockPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "thenBlock", boolean.class, Optional.empty(), false, false, false, false, false);
+        ifStmtMetaModel.thenBlockPropertyMetaModel = new PropertyMetaModel(ifStmtMetaModel, "thenBlock", boolean.class, Optional.empty(), false, false, false, false);
         ifStmtMetaModel.getDerivedPropertyMetaModels().add(ifStmtMetaModel.thenBlockPropertyMetaModel);
-        labeledStmtMetaModel.labelPropertyMetaModel = new PropertyMetaModel(labeledStmtMetaModel, "label", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        labeledStmtMetaModel.labelPropertyMetaModel = new PropertyMetaModel(labeledStmtMetaModel, "label", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         labeledStmtMetaModel.getDeclaredPropertyMetaModels().add(labeledStmtMetaModel.labelPropertyMetaModel);
-        labeledStmtMetaModel.statementPropertyMetaModel = new PropertyMetaModel(labeledStmtMetaModel, "statement", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false, false);
+        labeledStmtMetaModel.statementPropertyMetaModel = new PropertyMetaModel(labeledStmtMetaModel, "statement", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false);
         labeledStmtMetaModel.getDeclaredPropertyMetaModels().add(labeledStmtMetaModel.statementPropertyMetaModel);
-        returnStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(returnStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
+        returnStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(returnStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false);
         returnStmtMetaModel.getDeclaredPropertyMetaModels().add(returnStmtMetaModel.expressionPropertyMetaModel);
-        switchEntryStmtMetaModel.labelPropertyMetaModel = new PropertyMetaModel(switchEntryStmtMetaModel, "label", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), true, false, false, false, false);
-        switchEntryStmtMetaModel.getDeclaredPropertyMetaModels().add(switchEntryStmtMetaModel.labelPropertyMetaModel);
-        switchEntryStmtMetaModel.statementsPropertyMetaModel = new PropertyMetaModel(switchEntryStmtMetaModel, "statements", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, true, false, false);
-        switchEntryStmtMetaModel.getDeclaredPropertyMetaModels().add(switchEntryStmtMetaModel.statementsPropertyMetaModel);
-        switchStmtMetaModel.entriesPropertyMetaModel = new PropertyMetaModel(switchStmtMetaModel, "entries", com.github.javaparser.ast.stmt.SwitchEntryStmt.class, Optional.of(switchEntryStmtMetaModel), false, false, true, false, false);
+        switchEntryMetaModel.labelsPropertyMetaModel = new PropertyMetaModel(switchEntryMetaModel, "labels", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
+        switchEntryMetaModel.getDeclaredPropertyMetaModels().add(switchEntryMetaModel.labelsPropertyMetaModel);
+        switchEntryMetaModel.statementsPropertyMetaModel = new PropertyMetaModel(switchEntryMetaModel, "statements", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, true, false);
+        switchEntryMetaModel.getDeclaredPropertyMetaModels().add(switchEntryMetaModel.statementsPropertyMetaModel);
+        switchEntryMetaModel.typePropertyMetaModel = new PropertyMetaModel(switchEntryMetaModel, "type", com.github.javaparser.ast.stmt.SwitchEntry.Type.class, Optional.empty(), false, false, false, false);
+        switchEntryMetaModel.getDeclaredPropertyMetaModels().add(switchEntryMetaModel.typePropertyMetaModel);
+        switchStmtMetaModel.entriesPropertyMetaModel = new PropertyMetaModel(switchStmtMetaModel, "entries", com.github.javaparser.ast.stmt.SwitchEntry.class, Optional.of(switchEntryMetaModel), false, false, true, false);
         switchStmtMetaModel.getDeclaredPropertyMetaModels().add(switchStmtMetaModel.entriesPropertyMetaModel);
-        switchStmtMetaModel.selectorPropertyMetaModel = new PropertyMetaModel(switchStmtMetaModel, "selector", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        switchStmtMetaModel.selectorPropertyMetaModel = new PropertyMetaModel(switchStmtMetaModel, "selector", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         switchStmtMetaModel.getDeclaredPropertyMetaModels().add(switchStmtMetaModel.selectorPropertyMetaModel);
-        synchronizedStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(synchronizedStmtMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false, false);
+        synchronizedStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(synchronizedStmtMetaModel, "body", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false);
         synchronizedStmtMetaModel.getDeclaredPropertyMetaModels().add(synchronizedStmtMetaModel.bodyPropertyMetaModel);
-        synchronizedStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(synchronizedStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        synchronizedStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(synchronizedStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         synchronizedStmtMetaModel.getDeclaredPropertyMetaModels().add(synchronizedStmtMetaModel.expressionPropertyMetaModel);
-        throwStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(throwStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        throwStmtMetaModel.expressionPropertyMetaModel = new PropertyMetaModel(throwStmtMetaModel, "expression", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         throwStmtMetaModel.getDeclaredPropertyMetaModels().add(throwStmtMetaModel.expressionPropertyMetaModel);
-        tryStmtMetaModel.catchClausesPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "catchClauses", com.github.javaparser.ast.stmt.CatchClause.class, Optional.of(catchClauseMetaModel), false, false, true, false, false);
+        tryStmtMetaModel.catchClausesPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "catchClauses", com.github.javaparser.ast.stmt.CatchClause.class, Optional.of(catchClauseMetaModel), false, false, true, false);
         tryStmtMetaModel.getDeclaredPropertyMetaModels().add(tryStmtMetaModel.catchClausesPropertyMetaModel);
-        tryStmtMetaModel.finallyBlockPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "finallyBlock", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), true, false, false, false, false);
+        tryStmtMetaModel.finallyBlockPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "finallyBlock", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), true, false, false, false);
         tryStmtMetaModel.getDeclaredPropertyMetaModels().add(tryStmtMetaModel.finallyBlockPropertyMetaModel);
-        tryStmtMetaModel.resourcesPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "resources", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false, false);
+        tryStmtMetaModel.resourcesPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "resources", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, true, false);
         tryStmtMetaModel.getDeclaredPropertyMetaModels().add(tryStmtMetaModel.resourcesPropertyMetaModel);
-        tryStmtMetaModel.tryBlockPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "tryBlock", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false, false);
+        tryStmtMetaModel.tryBlockPropertyMetaModel = new PropertyMetaModel(tryStmtMetaModel, "tryBlock", com.github.javaparser.ast.stmt.BlockStmt.class, Optional.of(blockStmtMetaModel), false, false, false, false);
         tryStmtMetaModel.getDeclaredPropertyMetaModels().add(tryStmtMetaModel.tryBlockPropertyMetaModel);
-        localClassDeclarationStmtMetaModel.classDeclarationPropertyMetaModel = new PropertyMetaModel(localClassDeclarationStmtMetaModel, "classDeclaration", com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class, Optional.of(classOrInterfaceDeclarationMetaModel), false, false, false, false, false);
+        localClassDeclarationStmtMetaModel.classDeclarationPropertyMetaModel = new PropertyMetaModel(localClassDeclarationStmtMetaModel, "classDeclaration", com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class, Optional.of(classOrInterfaceDeclarationMetaModel), false, false, false, false);
         localClassDeclarationStmtMetaModel.getDeclaredPropertyMetaModels().add(localClassDeclarationStmtMetaModel.classDeclarationPropertyMetaModel);
-        whileStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(whileStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false, false);
+        whileStmtMetaModel.bodyPropertyMetaModel = new PropertyMetaModel(whileStmtMetaModel, "body", com.github.javaparser.ast.stmt.Statement.class, Optional.of(statementMetaModel), false, false, false, false);
         whileStmtMetaModel.getDeclaredPropertyMetaModels().add(whileStmtMetaModel.bodyPropertyMetaModel);
-        whileStmtMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(whileStmtMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false, false);
+        whileStmtMetaModel.conditionPropertyMetaModel = new PropertyMetaModel(whileStmtMetaModel, "condition", com.github.javaparser.ast.expr.Expression.class, Optional.of(expressionMetaModel), false, false, false, false);
         whileStmtMetaModel.getDeclaredPropertyMetaModels().add(whileStmtMetaModel.conditionPropertyMetaModel);
-        arrayTypeMetaModel.componentTypePropertyMetaModel = new PropertyMetaModel(arrayTypeMetaModel, "componentType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
+        arrayTypeMetaModel.componentTypePropertyMetaModel = new PropertyMetaModel(arrayTypeMetaModel, "componentType", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false);
         arrayTypeMetaModel.getDeclaredPropertyMetaModels().add(arrayTypeMetaModel.componentTypePropertyMetaModel);
-        arrayTypeMetaModel.originPropertyMetaModel = new PropertyMetaModel(arrayTypeMetaModel, "origin", com.github.javaparser.ast.type.ArrayType.Origin.class, Optional.empty(), false, false, false, false, false);
+        arrayTypeMetaModel.originPropertyMetaModel = new PropertyMetaModel(arrayTypeMetaModel, "origin", com.github.javaparser.ast.type.ArrayType.Origin.class, Optional.empty(), false, false, false, false);
         arrayTypeMetaModel.getDeclaredPropertyMetaModels().add(arrayTypeMetaModel.originPropertyMetaModel);
-        classOrInterfaceTypeMetaModel.namePropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        classOrInterfaceTypeMetaModel.namePropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         classOrInterfaceTypeMetaModel.getDeclaredPropertyMetaModels().add(classOrInterfaceTypeMetaModel.namePropertyMetaModel);
-        classOrInterfaceTypeMetaModel.scopePropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "scope", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), true, false, false, false, false);
+        classOrInterfaceTypeMetaModel.scopePropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "scope", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), true, false, false, false);
         classOrInterfaceTypeMetaModel.getDeclaredPropertyMetaModels().add(classOrInterfaceTypeMetaModel.scopePropertyMetaModel);
-        classOrInterfaceTypeMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false, false);
+        classOrInterfaceTypeMetaModel.typeArgumentsPropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "typeArguments", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), true, false, true, false);
         classOrInterfaceTypeMetaModel.getDeclaredPropertyMetaModels().add(classOrInterfaceTypeMetaModel.typeArgumentsPropertyMetaModel);
-        classOrInterfaceTypeMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false, false);
+        classOrInterfaceTypeMetaModel.usingDiamondOperatorPropertyMetaModel = new PropertyMetaModel(classOrInterfaceTypeMetaModel, "usingDiamondOperator", boolean.class, Optional.empty(), false, false, false, false);
         classOrInterfaceTypeMetaModel.getDerivedPropertyMetaModels().add(classOrInterfaceTypeMetaModel.usingDiamondOperatorPropertyMetaModel);
-        intersectionTypeMetaModel.elementsPropertyMetaModel = new PropertyMetaModel(intersectionTypeMetaModel, "elements", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, true, true, false, false);
+        intersectionTypeMetaModel.elementsPropertyMetaModel = new PropertyMetaModel(intersectionTypeMetaModel, "elements", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, true, true, false);
         intersectionTypeMetaModel.getDeclaredPropertyMetaModels().add(intersectionTypeMetaModel.elementsPropertyMetaModel);
-        primitiveTypeMetaModel.typePropertyMetaModel = new PropertyMetaModel(primitiveTypeMetaModel, "type", com.github.javaparser.ast.type.PrimitiveType.Primitive.class, Optional.empty(), false, false, false, false, false);
+        primitiveTypeMetaModel.typePropertyMetaModel = new PropertyMetaModel(primitiveTypeMetaModel, "type", com.github.javaparser.ast.type.PrimitiveType.Primitive.class, Optional.empty(), false, false, false, false);
         primitiveTypeMetaModel.getDeclaredPropertyMetaModels().add(primitiveTypeMetaModel.typePropertyMetaModel);
-        typeParameterMetaModel.namePropertyMetaModel = new PropertyMetaModel(typeParameterMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false, false);
+        typeParameterMetaModel.namePropertyMetaModel = new PropertyMetaModel(typeParameterMetaModel, "name", com.github.javaparser.ast.expr.SimpleName.class, Optional.of(simpleNameMetaModel), false, false, false, false);
         typeParameterMetaModel.getDeclaredPropertyMetaModels().add(typeParameterMetaModel.namePropertyMetaModel);
-        typeParameterMetaModel.typeBoundPropertyMetaModel = new PropertyMetaModel(typeParameterMetaModel, "typeBound", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false, false);
+        typeParameterMetaModel.typeBoundPropertyMetaModel = new PropertyMetaModel(typeParameterMetaModel, "typeBound", com.github.javaparser.ast.type.ClassOrInterfaceType.class, Optional.of(classOrInterfaceTypeMetaModel), false, false, true, false);
         typeParameterMetaModel.getDeclaredPropertyMetaModels().add(typeParameterMetaModel.typeBoundPropertyMetaModel);
-        unionTypeMetaModel.elementsPropertyMetaModel = new PropertyMetaModel(unionTypeMetaModel, "elements", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, true, true, false, false);
+        unionTypeMetaModel.elementsPropertyMetaModel = new PropertyMetaModel(unionTypeMetaModel, "elements", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), false, true, true, false);
         unionTypeMetaModel.getDeclaredPropertyMetaModels().add(unionTypeMetaModel.elementsPropertyMetaModel);
-        wildcardTypeMetaModel.extendedTypePropertyMetaModel = new PropertyMetaModel(wildcardTypeMetaModel, "extendedType", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), true, false, false, false, false);
+        wildcardTypeMetaModel.extendedTypePropertyMetaModel = new PropertyMetaModel(wildcardTypeMetaModel, "extendedType", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), true, false, false, false);
         wildcardTypeMetaModel.getDeclaredPropertyMetaModels().add(wildcardTypeMetaModel.extendedTypePropertyMetaModel);
-        wildcardTypeMetaModel.superTypePropertyMetaModel = new PropertyMetaModel(wildcardTypeMetaModel, "superType", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), true, false, false, false, false);
+        wildcardTypeMetaModel.superTypePropertyMetaModel = new PropertyMetaModel(wildcardTypeMetaModel, "superType", com.github.javaparser.ast.type.ReferenceType.class, Optional.of(referenceTypeMetaModel), true, false, false, false);
         wildcardTypeMetaModel.getDeclaredPropertyMetaModels().add(wildcardTypeMetaModel.superTypePropertyMetaModel);
-        moduleRequiresStmtMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(moduleRequiresStmtMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.empty(), false, false, false, true, false);
-        moduleRequiresStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleRequiresStmtMetaModel.modifiersPropertyMetaModel);
-        moduleRequiresStmtMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleRequiresStmtMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
-        moduleRequiresStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleRequiresStmtMetaModel.namePropertyMetaModel);
-        moduleExportsStmtMetaModel.moduleNamesPropertyMetaModel = new PropertyMetaModel(moduleExportsStmtMetaModel, "moduleNames", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, true, false, false);
-        moduleExportsStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleExportsStmtMetaModel.moduleNamesPropertyMetaModel);
-        moduleExportsStmtMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleExportsStmtMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
-        moduleExportsStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleExportsStmtMetaModel.namePropertyMetaModel);
-        moduleProvidesStmtMetaModel.typePropertyMetaModel = new PropertyMetaModel(moduleProvidesStmtMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
-        moduleProvidesStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleProvidesStmtMetaModel.typePropertyMetaModel);
-        moduleProvidesStmtMetaModel.withTypesPropertyMetaModel = new PropertyMetaModel(moduleProvidesStmtMetaModel, "withTypes", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, true, false, false);
-        moduleProvidesStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleProvidesStmtMetaModel.withTypesPropertyMetaModel);
-        moduleUsesStmtMetaModel.typePropertyMetaModel = new PropertyMetaModel(moduleUsesStmtMetaModel, "type", com.github.javaparser.ast.type.Type.class, Optional.of(typeMetaModel), false, false, false, false, false);
-        moduleUsesStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleUsesStmtMetaModel.typePropertyMetaModel);
-        moduleOpensStmtMetaModel.moduleNamesPropertyMetaModel = new PropertyMetaModel(moduleOpensStmtMetaModel, "moduleNames", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, true, false, false);
-        moduleOpensStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleOpensStmtMetaModel.moduleNamesPropertyMetaModel);
-        moduleOpensStmtMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleOpensStmtMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false, false);
-        moduleOpensStmtMetaModel.getDeclaredPropertyMetaModels().add(moduleOpensStmtMetaModel.namePropertyMetaModel);
+        moduleRequiresDirectiveMetaModel.modifiersPropertyMetaModel = new PropertyMetaModel(moduleRequiresDirectiveMetaModel, "modifiers", com.github.javaparser.ast.Modifier.class, Optional.of(modifierMetaModel), false, false, true, false);
+        moduleRequiresDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleRequiresDirectiveMetaModel.modifiersPropertyMetaModel);
+        moduleRequiresDirectiveMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleRequiresDirectiveMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
+        moduleRequiresDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleRequiresDirectiveMetaModel.namePropertyMetaModel);
+        moduleExportsDirectiveMetaModel.moduleNamesPropertyMetaModel = new PropertyMetaModel(moduleExportsDirectiveMetaModel, "moduleNames", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, true, false);
+        moduleExportsDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleExportsDirectiveMetaModel.moduleNamesPropertyMetaModel);
+        moduleExportsDirectiveMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleExportsDirectiveMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
+        moduleExportsDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleExportsDirectiveMetaModel.namePropertyMetaModel);
+        moduleProvidesDirectiveMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleProvidesDirectiveMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
+        moduleProvidesDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleProvidesDirectiveMetaModel.namePropertyMetaModel);
+        moduleProvidesDirectiveMetaModel.withPropertyMetaModel = new PropertyMetaModel(moduleProvidesDirectiveMetaModel, "with", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, true, false);
+        moduleProvidesDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleProvidesDirectiveMetaModel.withPropertyMetaModel);
+        moduleUsesDirectiveMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleUsesDirectiveMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
+        moduleUsesDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleUsesDirectiveMetaModel.namePropertyMetaModel);
+        moduleOpensDirectiveMetaModel.moduleNamesPropertyMetaModel = new PropertyMetaModel(moduleOpensDirectiveMetaModel, "moduleNames", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, true, false);
+        moduleOpensDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleOpensDirectiveMetaModel.moduleNamesPropertyMetaModel);
+        moduleOpensDirectiveMetaModel.namePropertyMetaModel = new PropertyMetaModel(moduleOpensDirectiveMetaModel, "name", com.github.javaparser.ast.expr.Name.class, Optional.of(nameMetaModel), false, false, false, false);
+        moduleOpensDirectiveMetaModel.getDeclaredPropertyMetaModels().add(moduleOpensDirectiveMetaModel.namePropertyMetaModel);
     }
 
-    public static Optional<BaseNodeMetaModel> getNodeMetaModel(Class<? extends Node> c) {
+    public static Optional<BaseNodeMetaModel> getNodeMetaModel(Class<?> c) {
         for (BaseNodeMetaModel nodeMetaModel : nodeMetaModels) {
-            if (nodeMetaModel.getTypeNameGenerified().equals(c.getSimpleName())) {
+            if (nodeMetaModel.getTypeName().equals(c.getSimpleName())) {
                 return Optional.of(nodeMetaModel);
             }
         }
@@ -787,7 +794,7 @@
 
     public static final ModuleDeclarationMetaModel moduleDeclarationMetaModel = new ModuleDeclarationMetaModel(Optional.of(nodeMetaModel));
 
-    public static final ModuleStmtMetaModel moduleStmtMetaModel = new ModuleStmtMetaModel(Optional.of(nodeMetaModel));
+    public static final ModuleDirectiveMetaModel moduleDirectiveMetaModel = new ModuleDirectiveMetaModel(Optional.of(nodeMetaModel));
 
     public static final ArrayCreationLevelMetaModel arrayCreationLevelMetaModel = new ArrayCreationLevelMetaModel(Optional.of(nodeMetaModel));
 
@@ -795,6 +802,8 @@
 
     public static final PackageDeclarationMetaModel packageDeclarationMetaModel = new PackageDeclarationMetaModel(Optional.of(nodeMetaModel));
 
+    public static final ModifierMetaModel modifierMetaModel = new ModifierMetaModel(Optional.of(nodeMetaModel));
+
     public static final AnnotationDeclarationMetaModel annotationDeclarationMetaModel = new AnnotationDeclarationMetaModel(Optional.of(typeDeclarationMetaModel));
 
     public static final AnnotationMemberDeclarationMetaModel annotationMemberDeclarationMetaModel = new AnnotationMemberDeclarationMetaModel(Optional.of(bodyDeclarationMetaModel));
@@ -893,6 +902,8 @@
 
     public static final VariableDeclarationExprMetaModel variableDeclarationExprMetaModel = new VariableDeclarationExprMetaModel(Optional.of(expressionMetaModel));
 
+    public static final SwitchExprMetaModel switchExprMetaModel = new SwitchExprMetaModel(Optional.of(expressionMetaModel));
+
     public static final ImportDeclarationMetaModel importDeclarationMetaModel = new ImportDeclarationMetaModel(Optional.of(nodeMetaModel));
 
     public static final AssertStmtMetaModel assertStmtMetaModel = new AssertStmtMetaModel(Optional.of(statementMetaModel));
@@ -913,7 +924,7 @@
 
     public static final ExpressionStmtMetaModel expressionStmtMetaModel = new ExpressionStmtMetaModel(Optional.of(statementMetaModel));
 
-    public static final ForeachStmtMetaModel foreachStmtMetaModel = new ForeachStmtMetaModel(Optional.of(statementMetaModel));
+    public static final ForEachStmtMetaModel forEachStmtMetaModel = new ForEachStmtMetaModel(Optional.of(statementMetaModel));
 
     public static final ForStmtMetaModel forStmtMetaModel = new ForStmtMetaModel(Optional.of(statementMetaModel));
 
@@ -923,7 +934,7 @@
 
     public static final ReturnStmtMetaModel returnStmtMetaModel = new ReturnStmtMetaModel(Optional.of(statementMetaModel));
 
-    public static final SwitchEntryStmtMetaModel switchEntryStmtMetaModel = new SwitchEntryStmtMetaModel(Optional.of(statementMetaModel));
+    public static final SwitchEntryMetaModel switchEntryMetaModel = new SwitchEntryMetaModel(Optional.of(nodeMetaModel));
 
     public static final SwitchStmtMetaModel switchStmtMetaModel = new SwitchStmtMetaModel(Optional.of(statementMetaModel));
 
@@ -959,15 +970,15 @@
 
     public static final VarTypeMetaModel varTypeMetaModel = new VarTypeMetaModel(Optional.of(typeMetaModel));
 
-    public static final ModuleRequiresStmtMetaModel moduleRequiresStmtMetaModel = new ModuleRequiresStmtMetaModel(Optional.of(moduleStmtMetaModel));
+    public static final ModuleRequiresDirectiveMetaModel moduleRequiresDirectiveMetaModel = new ModuleRequiresDirectiveMetaModel(Optional.of(moduleDirectiveMetaModel));
 
-    public static final ModuleExportsStmtMetaModel moduleExportsStmtMetaModel = new ModuleExportsStmtMetaModel(Optional.of(moduleStmtMetaModel));
+    public static final ModuleExportsDirectiveMetaModel moduleExportsDirectiveMetaModel = new ModuleExportsDirectiveMetaModel(Optional.of(moduleDirectiveMetaModel));
 
-    public static final ModuleProvidesStmtMetaModel moduleProvidesStmtMetaModel = new ModuleProvidesStmtMetaModel(Optional.of(moduleStmtMetaModel));
+    public static final ModuleProvidesDirectiveMetaModel moduleProvidesDirectiveMetaModel = new ModuleProvidesDirectiveMetaModel(Optional.of(moduleDirectiveMetaModel));
 
-    public static final ModuleUsesStmtMetaModel moduleUsesStmtMetaModel = new ModuleUsesStmtMetaModel(Optional.of(moduleStmtMetaModel));
+    public static final ModuleUsesDirectiveMetaModel moduleUsesDirectiveMetaModel = new ModuleUsesDirectiveMetaModel(Optional.of(moduleDirectiveMetaModel));
 
-    public static final ModuleOpensStmtMetaModel moduleOpensStmtMetaModel = new ModuleOpensStmtMetaModel(Optional.of(moduleStmtMetaModel));
+    public static final ModuleOpensDirectiveMetaModel moduleOpensDirectiveMetaModel = new ModuleOpensDirectiveMetaModel(Optional.of(moduleDirectiveMetaModel));
 
     static {
         initializeNodeMetaModels();
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModifierMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModifierMetaModel.java
new file mode 100644
index 0000000..e70f64a
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModifierMetaModel.java
@@ -0,0 +1,12 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class ModifierMetaModel extends NodeMetaModel {
+
+    ModifierMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.Modifier.class, "Modifier", "com.github.javaparser.ast", false, false);
+    }
+
+    public PropertyMetaModel keywordPropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleDeclarationMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleDeclarationMetaModel.java
index 0cf3c3e..7add5b6 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleDeclarationMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleDeclarationMetaModel.java
@@ -10,9 +10,9 @@
 
     public PropertyMetaModel annotationsPropertyMetaModel;
 
-    public PropertyMetaModel isOpenPropertyMetaModel;
+    public PropertyMetaModel directivesPropertyMetaModel;
 
-    public PropertyMetaModel moduleStmtsPropertyMetaModel;
+    public PropertyMetaModel isOpenPropertyMetaModel;
 
     public PropertyMetaModel namePropertyMetaModel;
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleDirectiveMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleDirectiveMetaModel.java
new file mode 100644
index 0000000..11489b3
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleDirectiveMetaModel.java
@@ -0,0 +1,15 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+import com.github.javaparser.ast.Node;
+
+public class ModuleDirectiveMetaModel extends NodeMetaModel {
+
+    ModuleDirectiveMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleDirective.class, "ModuleDirective", "com.github.javaparser.ast.modules", true, false);
+    }
+
+    protected ModuleDirectiveMetaModel(Optional<BaseNodeMetaModel> superNodeMetaModel, Class<? extends Node> type, String name, String packageName, boolean isAbstract, boolean hasWildcard) {
+        super(superNodeMetaModel, type, name, packageName, isAbstract, hasWildcard);
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleExportsDirectiveMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleExportsDirectiveMetaModel.java
new file mode 100644
index 0000000..b42968a
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleExportsDirectiveMetaModel.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class ModuleExportsDirectiveMetaModel extends ModuleDirectiveMetaModel {
+
+    ModuleExportsDirectiveMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleExportsDirective.class, "ModuleExportsDirective", "com.github.javaparser.ast.modules", false, false);
+    }
+
+    public PropertyMetaModel moduleNamesPropertyMetaModel;
+
+    public PropertyMetaModel namePropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleExportsStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleExportsStmtMetaModel.java
deleted file mode 100644
index 7b6af7e..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleExportsStmtMetaModel.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-
-public class ModuleExportsStmtMetaModel extends ModuleStmtMetaModel {
-
-    ModuleExportsStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleExportsStmt.class, "ModuleExportsStmt", "com.github.javaparser.ast.modules", false, false);
-    }
-
-    public PropertyMetaModel moduleNamesPropertyMetaModel;
-
-    public PropertyMetaModel namePropertyMetaModel;
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleOpensDirectiveMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleOpensDirectiveMetaModel.java
new file mode 100644
index 0000000..f99c94c
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleOpensDirectiveMetaModel.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class ModuleOpensDirectiveMetaModel extends ModuleDirectiveMetaModel {
+
+    ModuleOpensDirectiveMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleOpensDirective.class, "ModuleOpensDirective", "com.github.javaparser.ast.modules", false, false);
+    }
+
+    public PropertyMetaModel moduleNamesPropertyMetaModel;
+
+    public PropertyMetaModel namePropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleOpensStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleOpensStmtMetaModel.java
deleted file mode 100644
index 16a5a48..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleOpensStmtMetaModel.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-
-public class ModuleOpensStmtMetaModel extends ModuleStmtMetaModel {
-
-    ModuleOpensStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleOpensStmt.class, "ModuleOpensStmt", "com.github.javaparser.ast.modules", false, false);
-    }
-
-    public PropertyMetaModel moduleNamesPropertyMetaModel;
-
-    public PropertyMetaModel namePropertyMetaModel;
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleProvidesDirectiveMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleProvidesDirectiveMetaModel.java
new file mode 100644
index 0000000..7d669e2
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleProvidesDirectiveMetaModel.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class ModuleProvidesDirectiveMetaModel extends ModuleDirectiveMetaModel {
+
+    ModuleProvidesDirectiveMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleProvidesDirective.class, "ModuleProvidesDirective", "com.github.javaparser.ast.modules", false, false);
+    }
+
+    public PropertyMetaModel namePropertyMetaModel;
+
+    public PropertyMetaModel withPropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleProvidesStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleProvidesStmtMetaModel.java
deleted file mode 100644
index 2c3bffc..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleProvidesStmtMetaModel.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-
-public class ModuleProvidesStmtMetaModel extends ModuleStmtMetaModel {
-
-    ModuleProvidesStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleProvidesStmt.class, "ModuleProvidesStmt", "com.github.javaparser.ast.modules", false, false);
-    }
-
-    public PropertyMetaModel typePropertyMetaModel;
-
-    public PropertyMetaModel withTypesPropertyMetaModel;
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleRequiresDirectiveMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleRequiresDirectiveMetaModel.java
new file mode 100644
index 0000000..0d023d5
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleRequiresDirectiveMetaModel.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class ModuleRequiresDirectiveMetaModel extends ModuleDirectiveMetaModel {
+
+    ModuleRequiresDirectiveMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleRequiresDirective.class, "ModuleRequiresDirective", "com.github.javaparser.ast.modules", false, false);
+    }
+
+    public PropertyMetaModel modifiersPropertyMetaModel;
+
+    public PropertyMetaModel namePropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleRequiresStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleRequiresStmtMetaModel.java
deleted file mode 100644
index 320a811..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleRequiresStmtMetaModel.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-
-public class ModuleRequiresStmtMetaModel extends ModuleStmtMetaModel {
-
-    ModuleRequiresStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleRequiresStmt.class, "ModuleRequiresStmt", "com.github.javaparser.ast.modules", false, false);
-    }
-
-    public PropertyMetaModel modifiersPropertyMetaModel;
-
-    public PropertyMetaModel namePropertyMetaModel;
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleStmtMetaModel.java
deleted file mode 100644
index 63ca214..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleStmtMetaModel.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-import com.github.javaparser.ast.Node;
-
-public class ModuleStmtMetaModel extends NodeMetaModel {
-
-    ModuleStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleStmt.class, "ModuleStmt", "com.github.javaparser.ast.modules", true, false);
-    }
-
-    protected ModuleStmtMetaModel(Optional<BaseNodeMetaModel> superNodeMetaModel, Class<? extends Node> type, String name, String packageName, boolean isAbstract, boolean hasWildcard) {
-        super(superNodeMetaModel, type, name, packageName, isAbstract, hasWildcard);
-    }
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleUsesDirectiveMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleUsesDirectiveMetaModel.java
new file mode 100644
index 0000000..2e86cc4
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleUsesDirectiveMetaModel.java
@@ -0,0 +1,12 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class ModuleUsesDirectiveMetaModel extends ModuleDirectiveMetaModel {
+
+    ModuleUsesDirectiveMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleUsesDirective.class, "ModuleUsesDirective", "com.github.javaparser.ast.modules", false, false);
+    }
+
+    public PropertyMetaModel namePropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleUsesStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleUsesStmtMetaModel.java
deleted file mode 100644
index bac9043..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ModuleUsesStmtMetaModel.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-
-public class ModuleUsesStmtMetaModel extends ModuleStmtMetaModel {
-
-    ModuleUsesStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.modules.ModuleUsesStmt.class, "ModuleUsesStmt", "com.github.javaparser.ast.modules", false, false);
-    }
-
-    public PropertyMetaModel typePropertyMetaModel;
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/NameMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/NameMetaModel.java
index cd54085..94a986d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/NameMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/NameMetaModel.java
@@ -8,8 +8,6 @@
         super(superBaseNodeMetaModel, com.github.javaparser.ast.expr.Name.class, "Name", "com.github.javaparser.ast.expr", false, false);
     }
 
-    public PropertyMetaModel annotationsPropertyMetaModel;
-
     public PropertyMetaModel identifierPropertyMetaModel;
 
     public PropertyMetaModel qualifierPropertyMetaModel;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/PropertyMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/PropertyMetaModel.java
index 5dcf4af..b415aba 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/PropertyMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/PropertyMetaModel.java
@@ -19,10 +19,9 @@
     private final boolean isOptional;
     private final boolean isNonEmpty;
     private final boolean isNodeList;
-    private final boolean isEnumSet;
     private final boolean hasWildcard;
 
-    public PropertyMetaModel(BaseNodeMetaModel containingNodeMetaModel, String name, Class<?> type, Optional<BaseNodeMetaModel> nodeReference, boolean isOptional, boolean isNonEmpty, boolean isNodeList, boolean isEnumSet, boolean hasWildcard) {
+    public PropertyMetaModel(BaseNodeMetaModel containingNodeMetaModel, String name, Class<?> type, Optional<BaseNodeMetaModel> nodeReference, boolean isOptional, boolean isNonEmpty, boolean isNodeList, boolean hasWildcard) {
         this.containingNodeMetaModel = containingNodeMetaModel;
         this.name = name;
         this.type = type;
@@ -30,7 +29,6 @@
         this.isOptional = isOptional;
         this.isNonEmpty = isNonEmpty;
         this.isNodeList = isNodeList;
-        this.isEnumSet = isEnumSet;
         this.hasWildcard = hasWildcard;
     }
 
@@ -119,13 +117,6 @@
     }
 
     /**
-     * @return whether this property is contained in an EnumSet.
-     */
-    public boolean isEnumSet() {
-        return isEnumSet;
-    }
-
-    /**
      * @return whether this property has a wildcard following it, like BodyDeclaration&lt;?&gt;.
      */
     public boolean hasWildcard() {
@@ -136,7 +127,7 @@
      * @return whether this property is not a list or set.
      */
     public boolean isSingular() {
-        return !(isNodeList || isEnumSet);
+        return !isNodeList;
     }
 
     @Override
@@ -165,7 +156,7 @@
     }
 
     /**
-     * @return the type of a single element of this property, so no Optional or NodeList or EnumSet.
+     * @return the type of a single element of this property, so no Optional or NodeList.
      */
     public String getTypeNameGenerified() {
         if (hasWildcard) {
@@ -198,9 +189,6 @@
         if (isNodeList) {
             return "NodeList<" + getTypeNameGenerified() + ">";
         }
-        if (isEnumSet) {
-            return "EnumSet<" + getTypeNameGenerified() + ">";
-        }
         return getTypeNameGenerified();
     }
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/SuperExprMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/SuperExprMetaModel.java
index 745df8b..8ec9565 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/SuperExprMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/SuperExprMetaModel.java
@@ -8,5 +8,5 @@
         super(superBaseNodeMetaModel, com.github.javaparser.ast.expr.SuperExpr.class, "SuperExpr", "com.github.javaparser.ast.expr", false, false);
     }
 
-    public PropertyMetaModel classExprPropertyMetaModel;
+    public PropertyMetaModel typeNamePropertyMetaModel;
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchEntryMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchEntryMetaModel.java
new file mode 100644
index 0000000..27eb882
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchEntryMetaModel.java
@@ -0,0 +1,16 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class SwitchEntryMetaModel extends NodeMetaModel {
+
+    SwitchEntryMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.stmt.SwitchEntry.class, "SwitchEntry", "com.github.javaparser.ast.stmt", false, false);
+    }
+
+    public PropertyMetaModel labelsPropertyMetaModel;
+
+    public PropertyMetaModel statementsPropertyMetaModel;
+
+    public PropertyMetaModel typePropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchEntryStmtMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchEntryStmtMetaModel.java
deleted file mode 100644
index b8e6252..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchEntryStmtMetaModel.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import java.util.Optional;
-
-public class SwitchEntryStmtMetaModel extends StatementMetaModel {
-
-    SwitchEntryStmtMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
-        super(superBaseNodeMetaModel, com.github.javaparser.ast.stmt.SwitchEntryStmt.class, "SwitchEntryStmt", "com.github.javaparser.ast.stmt", false, false);
-    }
-
-    public PropertyMetaModel labelPropertyMetaModel;
-
-    public PropertyMetaModel statementsPropertyMetaModel;
-}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchExprMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchExprMetaModel.java
new file mode 100644
index 0000000..bcbc1ad
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/SwitchExprMetaModel.java
@@ -0,0 +1,14 @@
+package com.github.javaparser.metamodel;
+
+import java.util.Optional;
+
+public class SwitchExprMetaModel extends ExpressionMetaModel {
+
+    SwitchExprMetaModel(Optional<BaseNodeMetaModel> superBaseNodeMetaModel) {
+        super(superBaseNodeMetaModel, com.github.javaparser.ast.expr.SwitchExpr.class, "SwitchExpr", "com.github.javaparser.ast.expr", false, false);
+    }
+
+    public PropertyMetaModel entriesPropertyMetaModel;
+
+    public PropertyMetaModel selectorPropertyMetaModel;
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ThisExprMetaModel.java b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ThisExprMetaModel.java
index fbfd5a5..660f5dc 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/metamodel/ThisExprMetaModel.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/metamodel/ThisExprMetaModel.java
@@ -8,5 +8,5 @@
         super(superBaseNodeMetaModel, com.github.javaparser.ast.expr.ThisExpr.class, "ThisExpr", "com.github.javaparser.ast.expr", false, false);
     }
 
-    public PropertyMetaModel classExprPropertyMetaModel;
+    public PropertyMetaModel typeNamePropertyMetaModel;
 }
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 e45ed75..18538c8 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
@@ -42,7 +42,6 @@
 import static com.github.javaparser.ast.observer.ObservableProperty.*;
 import static com.github.javaparser.printer.concretesyntaxmodel.CsmConditional.Condition.*;
 import static com.github.javaparser.printer.concretesyntaxmodel.CsmElement.*;
-import static com.github.javaparser.utils.Utils.EOL;
 
 /**
  * The Concrete Syntax Model for a single node type. It knows the syntax used to represent a certain element in Java
@@ -73,13 +72,13 @@
     }
 
     private static CsmElement typeParameters() {
-        return list(ObservableProperty.TYPE_PARAMETERS, CsmElement.sequence(CsmElement.comma(), CsmElement.space()), CsmElement.token(GeneratedJavaParserConstants.LT),
-                CsmElement.sequence(CsmElement.token(GeneratedJavaParserConstants.GT), CsmElement.space()));
+        return list(ObservableProperty.TYPE_PARAMETERS, sequence(comma(), space()), token(GeneratedJavaParserConstants.LT),
+                sequence(token(GeneratedJavaParserConstants.GT), space()));
     }
 
     private static CsmElement typeArguments() {
-        return list(ObservableProperty.TYPE_ARGUMENTS, CsmElement.sequence(CsmElement.comma(), CsmElement.space()), CsmElement.token(GeneratedJavaParserConstants.LT),
-                CsmElement.sequence(CsmElement.token(GeneratedJavaParserConstants.GT)));
+        return list(ObservableProperty.TYPE_ARGUMENTS, sequence(comma(), space()), token(GeneratedJavaParserConstants.LT),
+                sequence(token(GeneratedJavaParserConstants.GT)));
     }
 
     static {
@@ -88,39 +87,39 @@
         /// Body
         ///
 
-        concreteSyntaxModelByClass.put(AnnotationDeclaration.class, CsmElement.sequence(
-                CsmElement.comment(),
+        concreteSyntaxModelByClass.put(AnnotationDeclaration.class, sequence(
+                comment(),
                 memberAnnotations(),
                 modifiers(),
-                CsmElement.token(GeneratedJavaParserConstants.AT),
-                CsmElement.token(GeneratedJavaParserConstants.INTERFACE),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.space(),
-                CsmElement.token(LBRACE),
-                CsmElement.newline(),
-                CsmElement.indent(),
-                CsmElement.list(ObservableProperty.MEMBERS, CsmElement.newline(), CsmElement.none(), CsmElement.none(), CsmElement.newline()),
-                CsmElement.unindent(),
-                CsmElement.token(RBRACE)
+                token(GeneratedJavaParserConstants.AT),
+                token(GeneratedJavaParserConstants.INTERFACE),
+                space(),
+                child(ObservableProperty.NAME),
+                space(),
+                token(LBRACE),
+                newline(),
+                indent(),
+                list(ObservableProperty.MEMBERS, newline(), none(), none(), newline()),
+                unindent(),
+                token(RBRACE)
         ));
 
-        concreteSyntaxModelByClass.put(AnnotationMemberDeclaration.class, CsmElement.sequence(
-                CsmElement.comment(),
+        concreteSyntaxModelByClass.put(AnnotationMemberDeclaration.class, sequence(
+                comment(),
                 memberAnnotations(),
                 modifiers(),
-                CsmElement.child(ObservableProperty.TYPE),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.token(LPAREN),
-                CsmElement.token(RPAREN),
-                CsmElement.conditional(ObservableProperty.DEFAULT_VALUE, IS_PRESENT, CsmElement.sequence(CsmElement.space(), CsmElement.token(GeneratedJavaParserConstants._DEFAULT), CsmElement.space(), CsmElement.child(DEFAULT_VALUE))),
-                CsmElement.semicolon()
+                child(ObservableProperty.TYPE),
+                space(),
+                child(ObservableProperty.NAME),
+                token(LPAREN),
+                token(RPAREN),
+                conditional(ObservableProperty.DEFAULT_VALUE, IS_PRESENT, sequence(space(), token(GeneratedJavaParserConstants._DEFAULT), space(), child(DEFAULT_VALUE))),
+                semicolon()
         ));
 
         concreteSyntaxModelByClass.put(ClassOrInterfaceDeclaration.class, sequence(
                 comment(),
-                list(ObservableProperty.ANNOTATIONS, newline(), none(), newline()),
+                memberAnnotations(),
                 modifiers(),
                 conditional(ObservableProperty.INTERFACE, FLAG, token(GeneratedJavaParserConstants.INTERFACE), token(GeneratedJavaParserConstants.CLASS)),
                 space(),
@@ -135,7 +134,7 @@
                         token(GeneratedJavaParserConstants.IMPLEMENTS),
                         space()), none()),
                 space(),
-                block(sequence(newline(), list(ObservableProperty.MEMBERS, sequence(newline(), newline()), CsmElement.newline(), newline())))
+                block(sequence(newline(), list(ObservableProperty.MEMBERS, sequence(newline(), newline()), newline(), newline())))
         ));
 
         concreteSyntaxModelByClass.put(ConstructorDeclaration.class, sequence(
@@ -157,10 +156,10 @@
                 memberAnnotations(),
                 child(ObservableProperty.NAME),
                 list(ObservableProperty.ARGUMENTS, sequence(comma(), space()), token(GeneratedJavaParserConstants.LPAREN), token(GeneratedJavaParserConstants.RPAREN)),
-                conditional(CLASS_BODY, IS_NOT_EMPTY, sequence(space(), token(GeneratedJavaParserConstants.LBRACE), CsmElement.newline(), CsmElement.indent(), CsmElement.newline(),
-                        list(ObservableProperty.CLASS_BODY, newline(), newline(), none(), CsmElement.newline()),
+                conditional(CLASS_BODY, IS_NOT_EMPTY, sequence(space(), token(GeneratedJavaParserConstants.LBRACE), newline(), indent(), newline(),
+                        list(ObservableProperty.CLASS_BODY, newline(), newline(), none(), newline()),
                         unindent(),
-                        token(RBRACE), CsmElement.newline()))
+                        token(RBRACE), newline()))
         ));
 
         concreteSyntaxModelByClass.put(EnumDeclaration.class, sequence(
@@ -176,16 +175,16 @@
                         none()),
                 space(),
                 token(GeneratedJavaParserConstants.LBRACE),
-                CsmElement.newline(),
-                CsmElement.indent(),
-                CsmElement.newline(),
+                newline(),
+                indent(),
+                newline(),
                 list(ObservableProperty.ENTRIES,
-                        sequence(comma(), space()),
-                        CsmElement.none(),
+                        sequence(comma(), newline()),
+                        none(),
                         none()),
                 conditional(ObservableProperty.MEMBERS, IS_EMPTY,
                         conditional(ObservableProperty.ENTRIES, IS_NOT_EMPTY, newline()),
-                        sequence(CsmElement.semicolon(), newline(), CsmElement.newline(), list(ObservableProperty.MEMBERS, newline(), newline(), none(), CsmElement.newline()))),
+                        sequence(semicolon(), newline(), newline(), list(ObservableProperty.MEMBERS, newline(), newline(), none(), newline()))),
                 unindent(),
                 token(RBRACE)
         ));
@@ -223,18 +222,18 @@
 
         concreteSyntaxModelByClass.put(Parameter.class, sequence(
                 comment(),
-                list(ObservableProperty.ANNOTATIONS, CsmElement.space(), CsmElement.none(), CsmElement.space()),
+                list(ObservableProperty.ANNOTATIONS, space(), none(), space()),
                 modifiers(),
                 child(ObservableProperty.TYPE),
-                conditional(ObservableProperty.VAR_ARGS, FLAG, CsmElement.sequence(
-                        list(ObservableProperty.VAR_ARGS_ANNOTATIONS, CsmElement.space(), CsmElement.none(), CsmElement.none()),
+                conditional(ObservableProperty.VAR_ARGS, FLAG, sequence(
+                        list(ObservableProperty.VAR_ARGS_ANNOTATIONS, space(), none(), none()),
                         token(GeneratedJavaParserConstants.ELLIPSIS))),
                 space(),
                 child(ObservableProperty.NAME)));
 
         concreteSyntaxModelByClass.put(ReceiverParameter.class, sequence(
                 comment(),
-                list(ObservableProperty.ANNOTATIONS, CsmElement.space(), CsmElement.none(), CsmElement.space()),
+                list(ObservableProperty.ANNOTATIONS, space(), none(), space()),
                 child(ObservableProperty.TYPE),
                 space(),
                 child(ObservableProperty.NAME)));
@@ -252,19 +251,19 @@
         /// Expressions
         ///
 
-        concreteSyntaxModelByClass.put(ArrayAccessExpr.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.token(GeneratedJavaParserConstants.LBRACKET),
-                CsmElement.child(ObservableProperty.INDEX),
-                CsmElement.token(GeneratedJavaParserConstants.RBRACKET)
+        concreteSyntaxModelByClass.put(ArrayAccessExpr.class, sequence(
+                comment(),
+                child(ObservableProperty.NAME),
+                token(GeneratedJavaParserConstants.LBRACKET),
+                child(ObservableProperty.INDEX),
+                token(GeneratedJavaParserConstants.RBRACKET)
         ));
 
         concreteSyntaxModelByClass.put(ArrayCreationExpr.class, sequence(
                 comment(),
                 token(GeneratedJavaParserConstants.NEW),
                 space(),
-                CsmElement.child(ObservableProperty.ELEMENT_TYPE),
+                child(ObservableProperty.ELEMENT_TYPE),
                 list(ObservableProperty.LEVELS),
                 conditional(ObservableProperty.INITIALIZER, IS_PRESENT, sequence(space(), child(ObservableProperty.INITIALIZER)))
         ));
@@ -315,17 +314,17 @@
         concreteSyntaxModelByClass.put(ClassExpr.class, sequence(
                 comment(), child(ObservableProperty.TYPE), token(GeneratedJavaParserConstants.DOT), token(GeneratedJavaParserConstants.CLASS)));
 
-        concreteSyntaxModelByClass.put(ConditionalExpr.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.child(ObservableProperty.CONDITION),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.HOOK),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.THEN_EXPR),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.COLON),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.ELSE_EXPR)
+        concreteSyntaxModelByClass.put(ConditionalExpr.class, sequence(
+                comment(),
+                child(ObservableProperty.CONDITION),
+                space(),
+                token(GeneratedJavaParserConstants.HOOK),
+                space(),
+                child(ObservableProperty.THEN_EXPR),
+                space(),
+                token(GeneratedJavaParserConstants.COLON),
+                space(),
+                child(ObservableProperty.ELSE_EXPR)
         ));
 
         concreteSyntaxModelByClass.put(DoubleLiteralExpr.class, sequence(
@@ -340,10 +339,10 @@
                 token(GeneratedJavaParserConstants.RPAREN)
         ));
 
-        concreteSyntaxModelByClass.put(FieldAccessExpr.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.child(SCOPE), 
-                CsmElement.token(GeneratedJavaParserConstants.DOT),
+        concreteSyntaxModelByClass.put(FieldAccessExpr.class, sequence(
+                comment(),
+                child(SCOPE),
+                token(GeneratedJavaParserConstants.DOT),
                 child(ObservableProperty.NAME)
         ));
 
@@ -379,12 +378,12 @@
 
         concreteSyntaxModelByClass.put(MarkerAnnotationExpr.class, sequence(comment(), token(GeneratedJavaParserConstants.AT), attribute(ObservableProperty.NAME)));
 
-        concreteSyntaxModelByClass.put(MemberValuePair.class, CsmElement.sequence(CsmElement.comment(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.ASSIGN),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.VALUE)));
+        concreteSyntaxModelByClass.put(MemberValuePair.class, sequence(comment(),
+                child(ObservableProperty.NAME),
+                space(),
+                token(GeneratedJavaParserConstants.ASSIGN),
+                space(),
+                child(ObservableProperty.VALUE)));
 
         concreteSyntaxModelByClass.put(MethodCallExpr.class, sequence(
                 comment(),
@@ -404,10 +403,11 @@
                 attribute(ObservableProperty.IDENTIFIER)
         ));
 
+        concreteSyntaxModelByClass.put(Modifier.class, attribute(ObservableProperty.KEYWORD));
+
         concreteSyntaxModelByClass.put(Name.class, sequence(
                 comment(),
                 conditional(ObservableProperty.QUALIFIER, IS_PRESENT, sequence(child(ObservableProperty.QUALIFIER), token(GeneratedJavaParserConstants.DOT))),
-                list(ObservableProperty.ANNOTATIONS, CsmElement.space(), CsmElement.none(), CsmElement.space()),
                 attribute(ObservableProperty.IDENTIFIER),
                 orphanCommentsEnding()
         ));
@@ -437,49 +437,49 @@
                 conditional(ObservableProperty.SCOPE, IS_PRESENT, sequence(child(ObservableProperty.SCOPE), token(GeneratedJavaParserConstants.DOT))),
                 token(GeneratedJavaParserConstants.NEW),
                 space(),
-                list(ObservableProperty.TYPE_ARGUMENTS, CsmElement.sequence(CsmElement.comma(), CsmElement.space()), CsmElement.token(LT), CsmElement.token(GT)),
+                list(ObservableProperty.TYPE_ARGUMENTS, sequence(comma(), space()), token(LT), token(GT)),
                 conditional(ObservableProperty.TYPE_ARGUMENTS, IS_NOT_EMPTY, space()),
                 child(ObservableProperty.TYPE),
                 token(GeneratedJavaParserConstants.LPAREN),
                 list(ObservableProperty.ARGUMENTS, sequence(comma(), space()), none(), none()),
                 token(GeneratedJavaParserConstants.RPAREN),
                 conditional(ObservableProperty.ANONYMOUS_CLASS_BODY, IS_PRESENT,
-                        CsmElement.sequence(
-                                CsmElement.space(), CsmElement.token(LBRACE), CsmElement.newline(), CsmElement.indent(),
-                                CsmElement.list(ObservableProperty.ANONYMOUS_CLASS_BODY,
-                                        CsmElement.newline(),
-                                        CsmElement.newline(),
-                                        CsmElement.newline(),
-                                        CsmElement.newline()),
-                                CsmElement.unindent(),
-                                CsmElement.token(RBRACE)
+                        sequence(
+                                space(), token(LBRACE), newline(), indent(),
+                                list(ObservableProperty.ANONYMOUS_CLASS_BODY,
+                                        newline(),
+                                        newline(),
+                                        newline(),
+                                        newline()),
+                                unindent(),
+                                token(RBRACE)
                         ))
         ));
 
         concreteSyntaxModelByClass.put(SimpleName.class, attribute(ObservableProperty.IDENTIFIER));
 
-        concreteSyntaxModelByClass.put(SingleMemberAnnotationExpr.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.AT),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.token(GeneratedJavaParserConstants.LPAREN),
-                CsmElement.child(ObservableProperty.MEMBER_VALUE),
-                CsmElement.token(GeneratedJavaParserConstants.RPAREN)));
+        concreteSyntaxModelByClass.put(SingleMemberAnnotationExpr.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.AT),
+                child(ObservableProperty.NAME),
+                token(GeneratedJavaParserConstants.LPAREN),
+                child(ObservableProperty.MEMBER_VALUE),
+                token(GeneratedJavaParserConstants.RPAREN)));
 
         concreteSyntaxModelByClass.put(StringLiteralExpr.class, sequence(
                 comment(),
                 stringToken(ObservableProperty.VALUE)
         ));
 
-        concreteSyntaxModelByClass.put(SuperExpr.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.conditional(ObservableProperty.CLASS_EXPR, IS_PRESENT, CsmElement.sequence(CsmElement.child(ObservableProperty.CLASS_EXPR), CsmElement.token(GeneratedJavaParserConstants.DOT))),
-                CsmElement.token(GeneratedJavaParserConstants.SUPER)
+        concreteSyntaxModelByClass.put(SuperExpr.class, sequence(
+                comment(),
+                conditional(TYPE_NAME, IS_PRESENT, sequence(child(TYPE_NAME), token(GeneratedJavaParserConstants.DOT))),
+                token(GeneratedJavaParserConstants.SUPER)
         ));
 
         concreteSyntaxModelByClass.put(ThisExpr.class, sequence(
                 comment(),
-                conditional(ObservableProperty.CLASS_EXPR, IS_PRESENT, sequence(child(CLASS_EXPR), token(GeneratedJavaParserConstants.DOT))),
+                conditional(TYPE_NAME, IS_PRESENT, sequence(child(TYPE_NAME), token(GeneratedJavaParserConstants.DOT))),
                 token(GeneratedJavaParserConstants.THIS)
         ));
 
@@ -496,7 +496,7 @@
 
         concreteSyntaxModelByClass.put(VariableDeclarationExpr.class, sequence(
                 comment(),
-                list(ObservableProperty.ANNOTATIONS, CsmElement.space(), CsmElement.none(), CsmElement.space()),
+                list(ObservableProperty.ANNOTATIONS, space(), none(), space()),
                 modifiers(),
                 child(ObservableProperty.MAXIMUM_COMMON_TYPE),
                 space(),
@@ -507,18 +507,18 @@
         /// Statements
         ///
 
-        concreteSyntaxModelByClass.put(AssertStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.ASSERT),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.CHECK),
-                CsmElement.conditional(ObservableProperty.MESSAGE, IS_PRESENT, CsmElement.sequence(
-                        CsmElement.space(),
-                        CsmElement.token(GeneratedJavaParserConstants.COLON),
-                        CsmElement.space(),
-                        CsmElement.child(ObservableProperty.MESSAGE)
+        concreteSyntaxModelByClass.put(AssertStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.ASSERT),
+                space(),
+                child(ObservableProperty.CHECK),
+                conditional(ObservableProperty.MESSAGE, IS_PRESENT, sequence(
+                        space(),
+                        token(GeneratedJavaParserConstants.COLON),
+                        space(),
+                        child(ObservableProperty.MESSAGE)
                 )),
-                CsmElement.semicolon()
+                semicolon()
         ));
 
         concreteSyntaxModelByClass.put(BlockStmt.class, sequence(
@@ -531,69 +531,69 @@
                 token(RBRACE)
         ));
 
-        concreteSyntaxModelByClass.put(BreakStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.BREAK),
-                CsmElement.conditional(ObservableProperty.LABEL, IS_PRESENT, CsmElement.sequence(CsmElement.space(), CsmElement.child(ObservableProperty.LABEL))),
-                CsmElement.semicolon()
+        concreteSyntaxModelByClass.put(BreakStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.BREAK),
+                conditional(VALUE, IS_PRESENT, sequence(space(), child(VALUE))),
+                semicolon()
         ));
 
-        concreteSyntaxModelByClass.put(CatchClause.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.CATCH),
-                CsmElement.space(),
-                CsmElement.token(LPAREN),
-                CsmElement.child(ObservableProperty.PARAMETER),
-                CsmElement.token(RPAREN),
-                CsmElement.space(),
-                CsmElement.child(BODY)
+        concreteSyntaxModelByClass.put(CatchClause.class, sequence(
+                comment(),
+                space(),
+                token(GeneratedJavaParserConstants.CATCH),
+                space(),
+                token(LPAREN),
+                child(ObservableProperty.PARAMETER),
+                token(RPAREN),
+                space(),
+                child(BODY)
         ));
 
-        concreteSyntaxModelByClass.put(ContinueStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.CONTINUE),
-                CsmElement.conditional(ObservableProperty.LABEL, IS_PRESENT, CsmElement.sequence(CsmElement.space(), CsmElement.child(ObservableProperty.LABEL))),
-                CsmElement.semicolon()
+        concreteSyntaxModelByClass.put(ContinueStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.CONTINUE),
+                conditional(ObservableProperty.LABEL, IS_PRESENT, sequence(space(), child(ObservableProperty.LABEL))),
+                semicolon()
         ));
 
-        concreteSyntaxModelByClass.put(DoStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.DO),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.BODY),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.WHILE),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.LPAREN),
+        concreteSyntaxModelByClass.put(DoStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.DO),
+                space(),
+                child(ObservableProperty.BODY),
+                space(),
+                token(GeneratedJavaParserConstants.WHILE),
+                space(),
+                token(GeneratedJavaParserConstants.LPAREN),
                 child(ObservableProperty.CONDITION),
-                CsmElement.token(GeneratedJavaParserConstants.RPAREN),
-                CsmElement.semicolon()
+                token(GeneratedJavaParserConstants.RPAREN),
+                semicolon()
         ));
 
-        concreteSyntaxModelByClass.put(EmptyStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.SEMICOLON)
+        concreteSyntaxModelByClass.put(EmptyStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.SEMICOLON)
         ));
 
-        concreteSyntaxModelByClass.put(UnparsableStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.SEMICOLON)
+        concreteSyntaxModelByClass.put(UnparsableStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.SEMICOLON)
         ));
 
-        concreteSyntaxModelByClass.put(ExplicitConstructorInvocationStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.conditional(ObservableProperty.THIS, FLAG,
-                        CsmElement.sequence(typeArguments(), CsmElement.token(GeneratedJavaParserConstants.THIS)),
-                        CsmElement.sequence(
-                                CsmElement.conditional(ObservableProperty.EXPRESSION, IS_PRESENT, CsmElement.sequence(CsmElement.child(ObservableProperty.EXPRESSION), CsmElement.token(GeneratedJavaParserConstants.DOT))),
+        concreteSyntaxModelByClass.put(ExplicitConstructorInvocationStmt.class, sequence(
+                comment(),
+                conditional(ObservableProperty.THIS, FLAG,
+                        sequence(typeArguments(), token(GeneratedJavaParserConstants.THIS)),
+                        sequence(
+                                conditional(ObservableProperty.EXPRESSION, IS_PRESENT, sequence(child(ObservableProperty.EXPRESSION), token(GeneratedJavaParserConstants.DOT))),
                                 typeArguments(),
-                                CsmElement.token(GeneratedJavaParserConstants.SUPER)
+                                token(GeneratedJavaParserConstants.SUPER)
                         )),
-                CsmElement.token(GeneratedJavaParserConstants.LPAREN),
-                CsmElement.list(ObservableProperty.ARGUMENTS, CsmElement.sequence(CsmElement.comma(), CsmElement.space())),
-                CsmElement.token(GeneratedJavaParserConstants.RPAREN),
-                CsmElement.semicolon()
+                token(GeneratedJavaParserConstants.LPAREN),
+                list(ObservableProperty.ARGUMENTS, sequence(comma(), space())),
+                token(GeneratedJavaParserConstants.RPAREN),
+                semicolon()
         ));
 
         concreteSyntaxModelByClass.put(ExpressionStmt.class, sequence(
@@ -603,7 +603,7 @@
                 semicolon()
         ));
 
-        concreteSyntaxModelByClass.put(ForeachStmt.class, sequence(
+        concreteSyntaxModelByClass.put(ForEachStmt.class, sequence(
                 comment(),
                 token(GeneratedJavaParserConstants.FOR),
                 space(),
@@ -645,66 +645,79 @@
                 conditional(ObservableProperty.THEN_BLOCK, CsmConditional.Condition.FLAG,
                         sequence(space(), child(ObservableProperty.THEN_STMT),
                                 conditional(ObservableProperty.ELSE_STMT, IS_PRESENT, space())),
-                        sequence(newline(), CsmElement.indent(), child(ObservableProperty.THEN_STMT),
+                        sequence(newline(), indent(), child(ObservableProperty.THEN_STMT),
                                 conditional(ObservableProperty.ELSE_STMT, IS_PRESENT, newline()),
                                 unindent())),
                 conditional(ObservableProperty.ELSE_STMT, IS_PRESENT,
                         sequence(token(GeneratedJavaParserConstants.ELSE),
                                 conditional(Arrays.asList(ObservableProperty.ELSE_BLOCK, ObservableProperty.CASCADING_IF_STMT), CsmConditional.Condition.FLAG,
                                         sequence(space(), child(ObservableProperty.ELSE_STMT)),
-                                        sequence(newline(), CsmElement.indent(), child(ObservableProperty.ELSE_STMT), unindent()))))
+                                        sequence(newline(), indent(), child(ObservableProperty.ELSE_STMT), unindent()))))
         ));
 
-        concreteSyntaxModelByClass.put(LabeledStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.child(ObservableProperty.LABEL),
-                CsmElement.token(GeneratedJavaParserConstants.COLON),
-                CsmElement.space(),
+        concreteSyntaxModelByClass.put(LabeledStmt.class, sequence(
+                comment(),
+                child(ObservableProperty.LABEL),
+                token(GeneratedJavaParserConstants.COLON),
+                space(),
                 child(ObservableProperty.STATEMENT)
         ));
 
-        concreteSyntaxModelByClass.put(LocalClassDeclarationStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.child(ObservableProperty.CLASS_DECLARATION)
+        concreteSyntaxModelByClass.put(LocalClassDeclarationStmt.class, sequence(
+                comment(),
+                child(ObservableProperty.CLASS_DECLARATION)
         ));
 
         concreteSyntaxModelByClass.put(ReturnStmt.class, sequence(comment(), token(GeneratedJavaParserConstants.RETURN),
                 conditional(ObservableProperty.EXPRESSION, IS_PRESENT, sequence(space(), child(ObservableProperty.EXPRESSION))),
                 semicolon()));
 
-        concreteSyntaxModelByClass.put(SwitchEntryStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.conditional(ObservableProperty.LABEL, IS_PRESENT,
-                        CsmElement.sequence(CsmElement.token(GeneratedJavaParserConstants.CASE), CsmElement.space(), CsmElement.child(ObservableProperty.LABEL), CsmElement.token(GeneratedJavaParserConstants.COLON)),
-                        CsmElement.sequence(CsmElement.token(GeneratedJavaParserConstants._DEFAULT), CsmElement.token(GeneratedJavaParserConstants.COLON))),
-                CsmElement.newline(),
-                CsmElement.indent(),
-                CsmElement.list(ObservableProperty.STATEMENTS, CsmElement.newline(), CsmElement.none(), CsmElement.newline()),
-                CsmElement.unindent()
+        concreteSyntaxModelByClass.put(SwitchEntry.class, sequence(
+                comment(),
+                conditional(ObservableProperty.LABELS, IS_NOT_EMPTY,
+                        sequence(token(GeneratedJavaParserConstants.CASE), space(), list(ObservableProperty.LABELS), token(GeneratedJavaParserConstants.COLON)),
+                        sequence(token(GeneratedJavaParserConstants._DEFAULT), token(GeneratedJavaParserConstants.COLON))),
+                newline(),
+                indent(),
+                list(ObservableProperty.STATEMENTS, newline(), none(), newline()),
+                unindent()
         ));
 
-        concreteSyntaxModelByClass.put(SwitchStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.SWITCH),
-                CsmElement.token(GeneratedJavaParserConstants.LPAREN),
-                CsmElement.child(ObservableProperty.SELECTOR),
-                CsmElement.token(GeneratedJavaParserConstants.RPAREN),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.LBRACE),
-                CsmElement.newline(),
-                CsmElement.list(ObservableProperty.ENTRIES, CsmElement.none(), CsmElement.indent(), CsmElement.unindent()),
-                CsmElement.token(GeneratedJavaParserConstants.RBRACE)
+        concreteSyntaxModelByClass.put(SwitchStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.SWITCH),
+                token(GeneratedJavaParserConstants.LPAREN),
+                child(ObservableProperty.SELECTOR),
+                token(GeneratedJavaParserConstants.RPAREN),
+                space(),
+                token(GeneratedJavaParserConstants.LBRACE),
+                newline(),
+                list(ObservableProperty.ENTRIES, none(), indent(), unindent()),
+                token(GeneratedJavaParserConstants.RBRACE)
         ));
 
-        concreteSyntaxModelByClass.put(SynchronizedStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.SYNCHRONIZED),
-                CsmElement.space(),
-                CsmElement.token(LPAREN),
-                CsmElement.child(EXPRESSION),
-                CsmElement.token(RPAREN),
-                CsmElement.space(),
-                CsmElement.child(BODY)
+        concreteSyntaxModelByClass.put(SwitchExpr.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.SWITCH),
+                token(GeneratedJavaParserConstants.LPAREN),
+                child(ObservableProperty.SELECTOR),
+                token(GeneratedJavaParserConstants.RPAREN),
+                space(),
+                token(GeneratedJavaParserConstants.LBRACE),
+                newline(),
+                list(ObservableProperty.ENTRIES, none(), indent(), unindent()),
+                token(GeneratedJavaParserConstants.RBRACE)
+        ));
+
+        concreteSyntaxModelByClass.put(SynchronizedStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.SYNCHRONIZED),
+                space(),
+                token(LPAREN),
+                child(EXPRESSION),
+                token(RPAREN),
+                space(),
+                child(BODY)
         ));
 
         concreteSyntaxModelByClass.put(ThrowStmt.class, sequence(
@@ -715,18 +728,18 @@
                 semicolon()
         ));
 
-        concreteSyntaxModelByClass.put(TryStmt.class, CsmElement.sequence(
-                CsmElement.comment(),
-                CsmElement.token(GeneratedJavaParserConstants.TRY),
-                CsmElement.space(),
-                CsmElement.conditional(ObservableProperty.RESOURCES, CsmConditional.Condition.IS_NOT_EMPTY, CsmElement.sequence(
-                        CsmElement.token(LPAREN),
-                        list(ObservableProperty.RESOURCES, CsmElement.sequence(CsmElement.semicolon(), CsmElement.newline()), CsmElement.indent(), CsmElement.unindent()),
-                        CsmElement.token(RPAREN),
-                        CsmElement.space())),
-                CsmElement.child(ObservableProperty.TRY_BLOCK),
-                CsmElement.list(ObservableProperty.CATCH_CLAUSES),
-                CsmElement.conditional(ObservableProperty.FINALLY_BLOCK, IS_PRESENT, CsmElement.sequence(CsmElement.space(), CsmElement.token(GeneratedJavaParserConstants.FINALLY), CsmElement.space(), CsmElement.child(ObservableProperty.FINALLY_BLOCK)))
+        concreteSyntaxModelByClass.put(TryStmt.class, sequence(
+                comment(),
+                token(GeneratedJavaParserConstants.TRY),
+                space(),
+                conditional(ObservableProperty.RESOURCES, CsmConditional.Condition.IS_NOT_EMPTY, sequence(
+                        token(LPAREN),
+                        list(ObservableProperty.RESOURCES, sequence(semicolon(), newline()), indent(), unindent()),
+                        token(RPAREN),
+                        space())),
+                child(ObservableProperty.TRY_BLOCK),
+                list(ObservableProperty.CATCH_CLAUSES),
+                conditional(ObservableProperty.FINALLY_BLOCK, IS_PRESENT, sequence(space(), token(GeneratedJavaParserConstants.FINALLY), space(), child(ObservableProperty.FINALLY_BLOCK)))
         ));
 
         concreteSyntaxModelByClass.put(WhileStmt.class, sequence(
@@ -758,10 +771,10 @@
                         sequence(string(GeneratedJavaParserConstants.LT), string(GeneratedJavaParserConstants.GT)),
                         list(TYPE_ARGUMENTS, sequence(comma(), space()), string(GeneratedJavaParserConstants.LT), string(GeneratedJavaParserConstants.GT)))));
 
-        concreteSyntaxModelByClass.put(IntersectionType.class, CsmElement.sequence(
-                CsmElement.comment(),
+        concreteSyntaxModelByClass.put(IntersectionType.class, sequence(
+                comment(),
                 annotations(),
-                CsmElement.list(ObservableProperty.ELEMENTS, CsmElement.sequence(CsmElement.space(), CsmElement.token(GeneratedJavaParserConstants.BIT_AND), CsmElement.space()))));
+                list(ObservableProperty.ELEMENTS, sequence(space(), token(GeneratedJavaParserConstants.BIT_AND), space()))));
 
         concreteSyntaxModelByClass.put(PrimitiveType.class, sequence(
                 comment(),
@@ -784,10 +797,10 @@
                         none())
         ));
 
-        concreteSyntaxModelByClass.put(UnionType.class, CsmElement.sequence(
-                CsmElement.comment(),
+        concreteSyntaxModelByClass.put(UnionType.class, sequence(
+                comment(),
                 annotations(),
-                CsmElement.list(ObservableProperty.ELEMENTS, CsmElement.sequence(CsmElement.space(), CsmElement.token(GeneratedJavaParserConstants.BIT_OR), CsmElement.space()))
+                list(ObservableProperty.ELEMENTS, sequence(space(), token(GeneratedJavaParserConstants.BIT_OR), space()))
         ));
 
         concreteSyntaxModelByClass.put(UnknownType.class, none());
@@ -797,8 +810,8 @@
         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)))));
+                conditional(ObservableProperty.EXTENDED_TYPE, IS_PRESENT, sequence(space(), token(GeneratedJavaParserConstants.EXTENDS), space(), child(EXTENDED_TYPE))),
+                conditional(ObservableProperty.SUPER_TYPE, IS_PRESENT, sequence(space(), token(GeneratedJavaParserConstants.SUPER), space(), child(SUPER_TYPE)))));
 
         ///
         /// Top Level
@@ -814,8 +827,8 @@
         concreteSyntaxModelByClass.put(CompilationUnit.class, sequence(
                 comment(),
                 child(ObservableProperty.PACKAGE_DECLARATION),
-                list(ObservableProperty.IMPORTS, none(), none(), newline()),
-                list(TYPES, newline(), CsmElement.newline(), CsmElement.none(), CsmElement.newline()),
+                list(ObservableProperty.IMPORTS, newline(), none(), sequence(newline(), newline())),
+                list(TYPES, newline(), newline(), none(), newline()),
                 child(ObservableProperty.MODULE),
                 orphanCommentsEnding()));
 
@@ -827,13 +840,12 @@
                 child(ObservableProperty.NAME),
                 conditional(ASTERISK, FLAG, sequence(token(GeneratedJavaParserConstants.DOT), token(GeneratedJavaParserConstants.STAR))),
                 semicolon(),
-                newline(),
                 orphanCommentsEnding()
         ));
 
         concreteSyntaxModelByClass.put(PackageDeclaration.class, sequence(
                 comment(),
-                list(ObservableProperty.ANNOTATIONS),
+                memberAnnotations(),
                 token(GeneratedJavaParserConstants.PACKAGE),
                 space(),
                 child(ObservableProperty.NAME),
@@ -846,73 +858,73 @@
         /// Module info
         ///
 
-        concreteSyntaxModelByClass.put(ModuleDeclaration.class, CsmElement.sequence(
-                annotations(),
-                CsmElement.conditional(ObservableProperty.OPEN, FLAG, CsmElement.sequence(CsmElement.token(GeneratedJavaParserConstants.OPEN), CsmElement.space())),
-                CsmElement.token(GeneratedJavaParserConstants.MODULE),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.space(),
-                CsmElement.token(GeneratedJavaParserConstants.LBRACE),
-                CsmElement.newline(),
-                CsmElement.indent(),
-                CsmElement.list(ObservableProperty.MODULE_STMTS),
-                CsmElement.unindent(),
-                CsmElement.token(GeneratedJavaParserConstants.RBRACE),
-                CsmElement.newline()
+        concreteSyntaxModelByClass.put(ModuleDeclaration.class, sequence(
+                memberAnnotations(),
+                conditional(ObservableProperty.OPEN, FLAG, sequence(token(GeneratedJavaParserConstants.OPEN), space())),
+                token(GeneratedJavaParserConstants.MODULE),
+                space(),
+                child(ObservableProperty.NAME),
+                space(),
+                token(GeneratedJavaParserConstants.LBRACE),
+                newline(),
+                indent(),
+                list(ObservableProperty.DIRECTIVES),
+                unindent(),
+                token(GeneratedJavaParserConstants.RBRACE),
+                newline()
         ));
 
-        concreteSyntaxModelByClass.put(ModuleExportsStmt.class, CsmElement.sequence(
-                CsmElement.token(GeneratedJavaParserConstants.EXPORTS),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.list(ObservableProperty.MODULE_NAMES,
-                        CsmElement.sequence(CsmElement.comma(), CsmElement.space()),
-                        CsmElement.sequence(CsmElement.space(), CsmElement.token(GeneratedJavaParserConstants.TO), CsmElement.space()),
-                        CsmElement.none()),
-                CsmElement.semicolon(),
-                CsmElement.newline()
+        concreteSyntaxModelByClass.put(ModuleExportsDirective.class, sequence(
+                token(GeneratedJavaParserConstants.EXPORTS),
+                space(),
+                child(ObservableProperty.NAME),
+                list(ObservableProperty.MODULE_NAMES,
+                        sequence(comma(), space()),
+                        sequence(space(), token(GeneratedJavaParserConstants.TO), space()),
+                        none()),
+                semicolon(),
+                newline()
         ));
 
-        concreteSyntaxModelByClass.put(ModuleOpensStmt.class, CsmElement.sequence(
-                CsmElement.token(GeneratedJavaParserConstants.OPENS),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.list(ObservableProperty.MODULE_NAMES,
-                        CsmElement.sequence(CsmElement.comma(), CsmElement.space()),
-                        CsmElement.sequence(CsmElement.space(), CsmElement.token(GeneratedJavaParserConstants.TO), CsmElement.space()),
-                        CsmElement.none()),
-                CsmElement.semicolon(),
-                CsmElement.newline()
+        concreteSyntaxModelByClass.put(ModuleOpensDirective.class, sequence(
+                token(GeneratedJavaParserConstants.OPENS),
+                space(),
+                child(ObservableProperty.NAME),
+                list(ObservableProperty.MODULE_NAMES,
+                        sequence(comma(), space()),
+                        sequence(space(), token(GeneratedJavaParserConstants.TO), space()),
+                        none()),
+                semicolon(),
+                newline()
         ));
 
-        concreteSyntaxModelByClass.put(ModuleProvidesStmt.class, CsmElement.sequence(
-                CsmElement.token(GeneratedJavaParserConstants.PROVIDES),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.TYPE),
-                CsmElement.list(ObservableProperty.WITH_TYPES,
-                        CsmElement.sequence(CsmElement.comma(), CsmElement.space()),
-                        CsmElement.sequence(CsmElement.space(), CsmElement.token(GeneratedJavaParserConstants.WITH), CsmElement.space()),
-                        CsmElement.none()),
-                CsmElement.semicolon(),
-                CsmElement.newline()
+        concreteSyntaxModelByClass.put(ModuleProvidesDirective.class, sequence(
+                token(GeneratedJavaParserConstants.PROVIDES),
+                space(),
+                child(ObservableProperty.NAME),
+                list(ObservableProperty.WITH,
+                        sequence(comma(), space()),
+                        sequence(space(), token(GeneratedJavaParserConstants.WITH), space()),
+                        none()),
+                semicolon(),
+                newline()
         ));
 
-        concreteSyntaxModelByClass.put(ModuleRequiresStmt.class, CsmElement.sequence(
-                CsmElement.token(GeneratedJavaParserConstants.REQUIRES),
-                CsmElement.space(),
+        concreteSyntaxModelByClass.put(ModuleRequiresDirective.class, sequence(
+                token(GeneratedJavaParserConstants.REQUIRES),
+                space(),
                 modifiers(),
-                CsmElement.child(ObservableProperty.NAME),
-                CsmElement.semicolon(),
-                CsmElement.newline()
+                child(ObservableProperty.NAME),
+                semicolon(),
+                newline()
         ));
 
-        concreteSyntaxModelByClass.put(ModuleUsesStmt.class, CsmElement.sequence(
-                CsmElement.token(GeneratedJavaParserConstants.USES),
-                CsmElement.space(),
-                CsmElement.child(ObservableProperty.TYPE),
-                CsmElement.semicolon(),
-                CsmElement.newline()
+        concreteSyntaxModelByClass.put(ModuleUsesDirective.class, sequence(
+                token(GeneratedJavaParserConstants.USES),
+                space(),
+                child(ObservableProperty.NAME),
+                semicolon(),
+                newline()
         ));
 
         List<String> unsupportedNodeClassNames = JavaParserMetaModel.getNodeMetaModels().stream()
@@ -935,9 +947,9 @@
     }
 
     public static String genericPrettyPrint(Node node) {
-        SourcePrinter sourcePrinter = new SourcePrinter("    ", EOL);
+        SourcePrinter sourcePrinter = new SourcePrinter();
         forClass(node.getClass()).prettyPrint(node, sourcePrinter);
-        return sourcePrinter.getSource();
+        return sourcePrinter.toString();
     }
 
     public static CsmElement forClass(Class<? extends Node> nodeClazz) {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/DotPrinter.java b/javaparser-core/src/main/java/com/github/javaparser/printer/DotPrinter.java
index 2e190c9..a5cf5ad 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/DotPrinter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/DotPrinter.java
@@ -21,6 +21,7 @@
 

 package com.github.javaparser.printer;

 

+import static com.github.javaparser.utils.Utils.EOL;

 import static com.github.javaparser.utils.Utils.assertNotNull;

 import static java.util.stream.Collectors.toList;

 

@@ -48,7 +49,7 @@
         StringBuilder output = new StringBuilder();

         output.append("digraph {");

         output(node, null, "root", output);

-        output.append(System.lineSeparator() + "}");

+        output.append(EOL + "}");

         return output.toString();

     }

 

@@ -65,19 +66,19 @@
 

         String ndName = nextNodeName();

         if (outputNodeType)

-            builder.append(System.lineSeparator() + ndName + " [label=\"" + name + " (" + metaModel.getTypeName()

+            builder.append(EOL + ndName + " [label=\"" + escape(name) + " (" + metaModel.getTypeName()

                     + ")\"];");

         else

-            builder.append(System.lineSeparator() + ndName + " [label=\"" + name + "\"];");

+            builder.append(EOL + ndName + " [label=\"" + escape(name) + "\"];");

 

         if (parentNodeName != null)

-            builder.append(System.lineSeparator() + parentNodeName + " -> " + ndName + ";");

+            builder.append(EOL + parentNodeName + " -> " + ndName + ";");

 

         for (PropertyMetaModel a : attributes) {

             String attrName = nextNodeName();

-            builder.append(System.lineSeparator() + attrName + " [label=\"" + a.getName() + "='"

-                    + a.getValue(node).toString() + "'\"];");

-            builder.append(System.lineSeparator() + ndName + " -> " + attrName + ";");

+            builder.append(EOL + attrName + " [label=\"" + escape(a.getName()) + "='"

+                    + escape(a.getValue(node).toString()) + "'\"];");

+            builder.append(EOL + ndName + " -> " + attrName + ";");

 

         }

 

@@ -91,8 +92,8 @@
             NodeList<? extends Node> nl = (NodeList<? extends Node>) sl.getValue(node);

             if (nl != null && nl.isNonEmpty()) {

                 String ndLstName = nextNodeName();

-                builder.append(System.lineSeparator() + ndLstName + " [label=\"" + sl.getName() + "\"];");

-                builder.append(System.lineSeparator() + ndName + " -> " + ndLstName + ";");

+                builder.append(EOL + ndLstName + " [label=\"" + escape(sl.getName()) + "\"];");

+                builder.append(EOL + ndName + " -> " + ndLstName + ";");

                 String slName = sl.getName().substring(0, sl.getName().length() - 1);

                 for (Node nd : nl)

                     output(nd, ndLstName, slName, builder);

@@ -103,4 +104,8 @@
     private String nextNodeName() {

         return "n" + (nodeCount++);

     }

+

+    private static String escape(String value) {

+        return value.replace("\"", "\\\"");

+    }

 }

diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/JsonPrinter.java b/javaparser-core/src/main/java/com/github/javaparser/printer/JsonPrinter.java
deleted file mode 100644
index 2370512..0000000
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/JsonPrinter.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.github.javaparser.printer;
-
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.metamodel.NodeMetaModel;
-import com.github.javaparser.metamodel.PropertyMetaModel;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import static java.util.stream.Collectors.toList;
-
-/**
- * Outputs a JSON file containing the AST meant for inspecting it.
- */
-public class JsonPrinter {
-    private final boolean outputNodeType;
-
-    public JsonPrinter(boolean outputNodeType) {
-        this.outputNodeType = outputNodeType;
-    }
-
-    public String output(Node node) {
-        return output(node, null, 0);
-    }
-
-    public String output(Node node, String name, int level) {
-        assertNotNull(node);
-        NodeMetaModel metaModel = node.getMetaModel();
-        List<PropertyMetaModel> allPropertyMetaModels = metaModel.getAllPropertyMetaModels();
-        List<PropertyMetaModel> attributes = allPropertyMetaModels.stream().filter(PropertyMetaModel::isAttribute).filter(PropertyMetaModel::isSingular).collect(toList());
-        List<PropertyMetaModel> subNodes = allPropertyMetaModels.stream().filter(PropertyMetaModel::isNode).filter(PropertyMetaModel::isSingular).collect(toList());
-        List<PropertyMetaModel> subLists = allPropertyMetaModels.stream().filter(PropertyMetaModel::isNodeList).collect(toList());
-
-        final List<String> content = new ArrayList<>();
-
-        if (outputNodeType) {
-            content.add(q("type") + ":" + q(metaModel.getTypeName()));
-        }
-
-        for (PropertyMetaModel attributeMetaModel : attributes) {
-            content.add(q(attributeMetaModel.getName()) + ":" + q(attributeMetaModel.getValue(node).toString()));
-        }
-
-        for (PropertyMetaModel subNodeMetaModel : subNodes) {
-            Node value = (Node) subNodeMetaModel.getValue(node);
-            if (value != null) {
-                content.add(output(value, subNodeMetaModel.getName(), level + 1));
-            }
-        }
-
-        for (PropertyMetaModel subListMetaModel : subLists) {
-            NodeList<? extends Node> subList = (NodeList<? extends Node>) subListMetaModel.getValue(node);
-            if (subList != null && !subList.isEmpty()) {
-                final List<String> listContent = new ArrayList<>();
-                for (Node subListNode : subList) {
-                    listContent.add(output(subListNode, null, level + 1));
-                }
-                content.add(listContent.stream().collect(Collectors.joining(",", q(subListMetaModel.getName()) + ":[", "]")));
-            }
-        }
-
-        if (name == null) {
-            return content.stream().collect(Collectors.joining(",", "{", "}"));
-        }
-        return content.stream().collect(Collectors.joining(",", q(name) + ":{", "}"));
-    }
-
-    private static String q(String value) {
-        return "\"" + value.replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r") + "\"";
-    }
-}
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 8a1d6b5..ee51c21 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
@@ -21,7 +21,6 @@
 
 package com.github.javaparser.printer;
 
-import com.github.javaparser.Position;
 import com.github.javaparser.ast.*;
 import com.github.javaparser.ast.body.*;
 import com.github.javaparser.ast.comments.BlockComment;
@@ -30,21 +29,20 @@
 import com.github.javaparser.ast.comments.LineComment;
 import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.modules.*;
-import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
-import com.github.javaparser.ast.nodeTypes.NodeWithVariables;
+import com.github.javaparser.ast.nodeTypes.*;
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
 import com.github.javaparser.ast.visitor.Visitable;
 import com.github.javaparser.ast.visitor.VoidVisitor;
 
 import java.util.*;
-import java.util.stream.Collectors;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
 import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition;
-import static com.github.javaparser.utils.Utils.isNullOrEmpty;
-import static com.github.javaparser.utils.Utils.normalizeEolInTextBlock;
-import static com.github.javaparser.utils.Utils.trimTrailingSpaces;
+import static com.github.javaparser.utils.Utils.*;
+import static java.util.Comparator.comparingInt;
+import static java.util.stream.Collectors.joining;
 
 /**
  * Outputs the AST as formatted Java source code.
@@ -54,38 +52,28 @@
 public class PrettyPrintVisitor implements VoidVisitor<Void> {
     protected final PrettyPrinterConfiguration configuration;
     protected final SourcePrinter printer;
-    private Deque<Position> methodChainPositions = new LinkedList<>();
 
     public PrettyPrintVisitor(PrettyPrinterConfiguration prettyPrinterConfiguration) {
         configuration = prettyPrinterConfiguration;
-        printer = new SourcePrinter(configuration.getIndent(), configuration.getEndOfLineCharacter());
-        pushMethodChainPosition(printer.getCursor()); // initialize a default position for methodChainPositions, it is expected by method #resetMethodChainPosition()
+        printer = new SourcePrinter(configuration);
     }
 
+    /**
+     * @deprecated use toString()
+     */
+    @Deprecated
     public String getSource() {
-        return printer.getSource();
+        return printer.toString();
     }
 
-    public void resetMethodChainPosition(Position position) {
-        this.methodChainPositions.pop();
-        this.methodChainPositions.push(position);
+    @Override
+    public String toString() {
+        return printer.toString();
     }
 
-    public void pushMethodChainPosition(Position position) {
-        this.methodChainPositions.push(position);
-    }
-
-    public Position peekMethodChainPosition() {
-        return this.methodChainPositions.peek();
-    }
-
-    public Position popMethodChainPosition() {
-        return this.methodChainPositions.pop();
-    }
-
-    private void printModifiers(final EnumSet<Modifier> modifiers) {
+    private void printModifiers(final NodeList<Modifier> modifiers) {
         if (modifiers.size() > 0) {
-            printer.print(modifiers.stream().map(Modifier::asString).collect(Collectors.joining(" ")) + " ");
+            printer.print(modifiers.stream().map(Modifier::getKeyword).map(Modifier.Keyword::asString).collect(joining(" ")) + " ");
         }
     }
 
@@ -152,20 +140,26 @@
 
     private void printArguments(final NodeList<Expression> args, final Void arg) {
         printer.print("(");
-        Position cursorRef = printer.getCursor();
         if (!isNullOrEmpty(args)) {
+            boolean columnAlignParameters = (args.size() > 1) && configuration.isColumnAlignParameters();
+            if (columnAlignParameters) {
+                printer.indentWithAlignTo(printer.getCursor().column);
+            }
             for (final Iterator<Expression> i = args.iterator(); i.hasNext(); ) {
                 final Expression e = i.next();
                 e.accept(this, arg);
                 if (i.hasNext()) {
                     printer.print(",");
-                    if (configuration.isColumnAlignParameters()) {
-                        printer.wrapToColumn(cursorRef.column);
+                    if (columnAlignParameters) {
+                        printer.println();
                     } else {
                         printer.print(" ");
                     }
                 }
             }
+            if (columnAlignParameters) {
+                printer.unindent();
+            }
         }
         printer.print(")");
     }
@@ -235,7 +229,7 @@
     @Override
     public void visit(final PackageDeclaration n, final Void arg) {
         printComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
+        printMemberAnnotations(n.getAnnotations(), arg);
         printer.print("package ");
         n.getName().accept(this, arg);
         printer.println(";");
@@ -259,7 +253,6 @@
             n.getQualifier().get().accept(this, arg);
             printer.print(".");
         }
-        printAnnotations(n.getAnnotations(), false, arg);
         printer.print(n.getIdentifier());
 
         printOrphanCommentsEnding(n);
@@ -326,14 +319,20 @@
             printer.println("/**");
             final String commentContent = normalizeEolInTextBlock(n.getContent(), configuration.getEndOfLineCharacter());
             String[] lines = commentContent.split("\\R");
-            boolean skippingLeadingEmptyLines = true;
-            boolean prependEmptyLine = false;
+            List<String> strippedLines = new ArrayList<>();
             for (String line : lines) {
                 final String trimmedLine = line.trim();
                 if (trimmedLine.startsWith("*")) {
                     line = trimmedLine.substring(1);
                 }
                 line = trimTrailingSpaces(line);
+                strippedLines.add(line);
+            }
+
+            boolean skippingLeadingEmptyLines = true;
+            boolean prependEmptyLine = false;
+            boolean prependSpace = strippedLines.stream().anyMatch(line -> !line.isEmpty() && !line.startsWith(" "));
+            for (String line : strippedLines) {
                 if (line.isEmpty()) {
                     if (!skippingLeadingEmptyLines) {
                         prependEmptyLine = true;
@@ -344,7 +343,11 @@
                         printer.println(" *");
                         prependEmptyLine = false;
                     }
-                    printer.println(" *" + line);
+                    printer.print(" *");
+                    if (prependSpace) {
+                        printer.print(" ");
+                    }
+                    printer.println(line);
                 }
             }
             printer.println(" */");
@@ -358,10 +361,7 @@
             n.getScope().get().accept(this, arg);
             printer.print(".");
         }
-        for (AnnotationExpr ae : n.getAnnotations()) {
-            ae.accept(this, arg);
-            printer.print(" ");
-        }
+        printAnnotations(n.getAnnotations(), false, arg);
 
         n.getName().accept(this, arg);
 
@@ -375,10 +375,7 @@
     @Override
     public void visit(final TypeParameter n, final Void arg) {
         printComment(n.getComment(), arg);
-        for (AnnotationExpr ann : n.getAnnotations()) {
-            ann.accept(this, arg);
-            printer.print(" ");
-        }
+        printAnnotations(n.getAnnotations(), false, arg);
         n.getName().accept(this, arg);
         if (!isNullOrEmpty(n.getTypeBound())) {
             printer.print(" extends ");
@@ -508,24 +505,22 @@
         printComment(n.getComment(), arg);
         n.getName().accept(this, arg);
 
-        n.getAncestorOfType(NodeWithVariables.class).ifPresent(ancestor -> {
-            ((NodeWithVariables<?>) ancestor).getMaximumCommonType().ifPresent(commonType -> {
+        n.findAncestor(NodeWithVariables.class).ifPresent(ancestor -> ((NodeWithVariables<?>) ancestor).getMaximumCommonType().ifPresent(commonType -> {
 
-                final Type type = n.getType();
+            final Type type = n.getType();
 
-                ArrayType arrayType = null;
+            ArrayType arrayType = null;
 
-                for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) {
-                    if (arrayType == null) {
-                        arrayType = (ArrayType) type;
-                    } else {
-                        arrayType = (ArrayType) arrayType.getComponentType();
-                    }
-                    printAnnotations(arrayType.getAnnotations(), true, arg);
-                    printer.print("[]");
+            for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) {
+                if (arrayType == null) {
+                    arrayType = (ArrayType) type;
+                } else {
+                    arrayType = (ArrayType) arrayType.getComponentType();
                 }
-            });
-        });
+                printAnnotations(arrayType.getAnnotations(), true, arg);
+                printer.print("[]");
+            }
+        }));
 
         if (n.getInitializer().isPresent()) {
             printer.print(" = ");
@@ -567,6 +562,12 @@
     }
 
     @Override
+    public void visit(Modifier n, Void arg) {
+        printer.print(n.getKeyword().asString());
+        printer.print(" ");
+    }
+
+    @Override
     public void visit(final ArrayAccessExpr n, final Void arg) {
         printComment(n.getComment(), arg);
         n.getName().accept(this, arg);
@@ -708,8 +709,8 @@
     @Override
     public void visit(final ThisExpr n, final Void arg) {
         printComment(n.getComment(), arg);
-        if (n.getClassExpr().isPresent()) {
-            n.getClassExpr().get().accept(this, arg);
+        if (n.getTypeName().isPresent()) {
+            n.getTypeName().get().accept(this, arg);
             printer.print(".");
         }
         printer.print("this");
@@ -718,8 +719,8 @@
     @Override
     public void visit(final SuperExpr n, final Void arg) {
         printComment(n.getComment(), arg);
-        if (n.getClassExpr().isPresent()) {
-            n.getClassExpr().get().accept(this, arg);
+        if (n.getTypeName().isPresent()) {
+            n.getTypeName().get().accept(this, arg);
             printer.print(".");
         }
         printer.print("super");
@@ -728,22 +729,104 @@
     @Override
     public void visit(final MethodCallExpr n, final Void arg) {
         printComment(n.getComment(), arg);
-        if (n.getScope().isPresent()) {
-            n.getScope().get().accept(this, arg);
-            if (configuration.isColumnAlignFirstMethodChain()) {
-                if (!(n.getScope().get() instanceof MethodCallExpr) || (!((MethodCallExpr) n.getScope().get()).getScope().isPresent())) {
-                    resetMethodChainPosition(printer.getCursor());
-                } else {
-                    printer.wrapToColumn(peekMethodChainPosition().column);
+
+        // determine whether we do reindenting for aligmnent at all
+        // - is it enabled?
+        // - are we in a statement where we want the alignment?
+        // - are we not directly in the argument list of a method call expression?
+        AtomicBoolean columnAlignFirstMethodChain = new AtomicBoolean();
+        if (configuration.isColumnAlignFirstMethodChain()) {
+            // pick the kind of expressions where vertically aligning method calls is okay.
+            if (n.findAncestor(Statement.class).map(p -> p.isReturnStmt()
+                    || p.isThrowStmt()
+                    || p.isAssertStmt()
+                    || p.isExpressionStmt()).orElse(false)) {
+                // search for first parent that does not have its child as scope
+                Node c = n;
+                Optional<Node> p = c.getParentNode();
+                while (p.isPresent() && p.filter(NodeWithTraversableScope.class::isInstance)
+                        .map(NodeWithTraversableScope.class::cast)
+                        .flatMap(NodeWithTraversableScope::traverseScope)
+                        .map(c::equals)
+                        .orElse(false)) {
+                    c = p.get();
+                    p = c.getParentNode();
+                }
+
+                // check if the parent is a method call and thus we are in an argument list
+                columnAlignFirstMethodChain.set(!p.filter(MethodCallExpr.class::isInstance).isPresent());
+            }
+        }
+
+        // we are at the last method call of a call chain
+        // this means we do not start reindenting for alignment or we undo it
+        AtomicBoolean lastMethodInCallChain = new AtomicBoolean(true);
+        if (columnAlignFirstMethodChain.get()) {
+            Node node = n;
+            while (node.getParentNode()
+                    .filter(NodeWithTraversableScope.class::isInstance)
+                    .map(NodeWithTraversableScope.class::cast)
+                    .flatMap(NodeWithTraversableScope::traverseScope)
+                    .map(node::equals)
+                    .orElse(false)) {
+                node = node.getParentNode().orElseThrow(AssertionError::new);
+                if (node instanceof MethodCallExpr) {
+                    lastMethodInCallChain.set(false);
+                    break;
+                }
+            }
+        }
+
+        // search whether there is a method call with scope in the scope already
+        // this means that we probably started reindenting for alignment there
+        AtomicBoolean methodCallWithScopeInScope = new AtomicBoolean();
+        if (columnAlignFirstMethodChain.get()) {
+            Optional<Expression> s = n.getScope();
+            while (s.filter(NodeWithTraversableScope.class::isInstance).isPresent()) {
+                Optional<Expression> parentScope = s.map(NodeWithTraversableScope.class::cast)
+                        .flatMap(NodeWithTraversableScope::traverseScope);
+                if (s.filter(MethodCallExpr.class::isInstance).isPresent() && parentScope.isPresent()) {
+                    methodCallWithScopeInScope.set(true);
+                    break;
+                }
+                s = parentScope;
+            }
+        }
+
+        // we have a scope
+        // this means we are not the first method in the chain
+        n.getScope().ifPresent(scope -> {
+            scope.accept(this, arg);
+            if (columnAlignFirstMethodChain.get()) {
+                if (methodCallWithScopeInScope.get()) {
+                    /* We're a method call on the result of something (method call, property access, ...) that is not stand alone,
+                       and not the first one with scope, like:
+                       we're x() in a.b().x(), or in a=b().c[15].d.e().x().
+                       That means that the "else" has been executed by one of the methods in the scope chain, so that the alignment
+                       is set to the "." of that method.
+                       That means we will align to that "." when we start a new line: */
+                    printer.println();
+                } else if (!lastMethodInCallChain.get()) {
+                    /* We're the first method call on the result of something in the chain (method call, property access, ...),
+                       but we are not at the same time the last method call in that chain, like:
+                       we're x() in a().x().y(), or in Long.x().y.z(). That means we get to dictate the indent of following method
+                       calls in this chain by setting the cursor to where we are now: just before the "."
+                       that start this method call. */
+                    printer.reindentWithAlignToCursor();
                 }
             }
             printer.print(".");
-        }
+        });
+
         printTypeArgs(n, arg);
         n.getName().accept(this, arg);
-        pushMethodChainPosition(printer.getCursor());
+        printer.duplicateIndent();
         printArguments(n.getArguments(), arg);
-        popMethodChainPosition();
+        printer.unindent();
+        if (columnAlignFirstMethodChain.get() && methodCallWithScopeInScope.get() && lastMethodInCallChain.get()) {
+            // undo the aligning after the arguments of the last method call are printed
+            printer.reindentToPreviousLevel();
+        }
     }
 
     @Override
@@ -845,7 +928,9 @@
         printer.print("(");
         n.getReceiverParameter().ifPresent(rp -> {
             rp.accept(this, arg);
-            printer.print(", ");
+            if (!isNullOrEmpty(n.getParameters())) {
+                printer.print(", ");
+            }
         });
         if (!isNullOrEmpty(n.getParameters())) {
             for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) {
@@ -922,7 +1007,11 @@
     @Override
     public void visit(final VariableDeclarationExpr n, final Void arg) {
         printComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
+        if (n.getParentNode().map(ExpressionStmt.class::isInstance).orElse(false)) {
+            printMemberAnnotations(n.getAnnotations(), arg);
+        } else {
+            printAnnotations(n.getAnnotations(), false, arg);
+        }
         printModifiers(n.getModifiers());
 
         if (!n.getVariables().isEmpty()) {
@@ -998,13 +1087,22 @@
 
     @Override
     public void visit(final SwitchStmt n, final Void arg) {
+        printSwitchNode(n, arg);
+    }
+
+    @Override
+    public void visit(SwitchExpr n, Void arg) {
+        printSwitchNode(n, arg);
+    }
+
+    private void printSwitchNode(SwitchNode n, Void arg) {
         printComment(n.getComment(), arg);
         printer.print("switch(");
         n.getSelector().accept(this, arg);
         printer.println(") {");
         if (n.getEntries() != null) {
             printer.indent();
-            for (final SwitchEntryStmt e : n.getEntries()) {
+            for (final SwitchEntry e : n.getEntries()) {
                 e.accept(this, arg);
             }
             printer.unindent();
@@ -1013,14 +1111,21 @@
     }
 
     @Override
-    public void visit(final SwitchEntryStmt n, final Void arg) {
+    public void visit(final SwitchEntry n, final Void arg) {
         printComment(n.getComment(), arg);
-        if (n.getLabel().isPresent()) {
-            printer.print("case ");
-            n.getLabel().get().accept(this, arg);
-            printer.print(":");
-        } else {
+
+        if (isNullOrEmpty(n.getLabels())) {
             printer.print("default:");
+        } else {
+            printer.print("case ");
+            for (final Iterator<Expression> i = n.getLabels().iterator(); i.hasNext(); ) {
+                final Expression label = i.next();
+                label.accept(this, arg);
+                if (i.hasNext()) {
+                    printer.print(", ");
+                }
+            }
+            printer.print(":");
         }
         printer.println();
         printer.indent();
@@ -1037,7 +1142,10 @@
     public void visit(final BreakStmt n, final Void arg) {
         printComment(n.getComment(), arg);
         printer.print("break");
-        n.getLabel().ifPresent(l -> printer.print(" ").print(l.getIdentifier()));
+        n.getValue().ifPresent(value -> {
+            printer.print(" ");
+            value.accept(this, arg);
+        });
         printer.print(";");
     }
 
@@ -1196,7 +1304,7 @@
     }
 
     @Override
-    public void visit(final ForeachStmt n, final Void arg) {
+    public void visit(final ForEachStmt n, final Void arg) {
         printComment(n.getComment(), arg);
         printer.print("for (");
         n.getVariable().accept(this, arg);
@@ -1460,13 +1568,9 @@
         if (configuration.isOrderImports() && n.size() > 0 && n.get(0) instanceof ImportDeclaration) {
             //noinspection unchecked
             NodeList<ImportDeclaration> modifiableList = new NodeList<>(n);
-            modifiableList.sort((left, right) -> {
-                int sort = Integer.compare(left.isStatic() ? 0 : 1, right.isStatic() ? 0 : 1);
-                if (sort == 0) {
-                    sort = left.getNameAsString().compareTo(right.getNameAsString());
-                }
-                return sort;
-            });
+            modifiableList.sort(
+                    comparingInt((ImportDeclaration i) -> i.isStatic() ? 0 : 1)
+                            .thenComparing(NodeWithName::getNameAsString));
             for (Object node : modifiableList) {
                 ((Node) node).accept(this, arg);
             }
@@ -1496,20 +1600,19 @@
 
     @Override
     public void visit(ModuleDeclaration n, Void arg) {
-        printAnnotations(n.getAnnotations(), false, arg);
-        printer.println();
+        printMemberAnnotations(n.getAnnotations(), arg);
         if (n.isOpen()) {
             printer.print("open ");
         }
         printer.print("module ");
         n.getName().accept(this, arg);
         printer.println(" {").indent();
-        n.getModuleStmts().accept(this, arg);
+        n.getDirectives().accept(this, arg);
         printer.unindent().println("}");
     }
 
     @Override
-    public void visit(ModuleRequiresStmt n, Void arg) {
+    public void visit(ModuleRequiresDirective n, Void arg) {
         printer.print("requires ");
         printModifiers(n.getModifiers());
         n.getName().accept(this, arg);
@@ -1517,7 +1620,7 @@
     }
 
     @Override
-    public void visit(ModuleExportsStmt n, Void arg) {
+    public void visit(ModuleExportsDirective n, Void arg) {
         printer.print("exports ");
         n.getName().accept(this, arg);
         printPrePostFixOptionalList(n.getModuleNames(), arg, " to ", ", ", "");
@@ -1525,22 +1628,22 @@
     }
 
     @Override
-    public void visit(ModuleProvidesStmt n, Void arg) {
+    public void visit(ModuleProvidesDirective n, Void arg) {
         printer.print("provides ");
-        n.getType().accept(this, arg);
-        printPrePostFixRequiredList(n.getWithTypes(), arg, " with ", ", ", "");
+        n.getName().accept(this, arg);
+        printPrePostFixRequiredList(n.getWith(), arg, " with ", ", ", "");
         printer.println(";");
     }
 
     @Override
-    public void visit(ModuleUsesStmt n, Void arg) {
+    public void visit(ModuleUsesDirective n, Void arg) {
         printer.print("uses ");
-        n.getType().accept(this, arg);
+        n.getName().accept(this, arg);
         printer.println(";");
     }
 
     @Override
-    public void visit(ModuleOpensStmt n, Void arg) {
+    public void visit(ModuleOpensDirective n, Void arg) {
         printer.print("opens ");
         n.getName().accept(this, arg);
         printPrePostFixOptionalList(n.getModuleNames(), arg, " to ", ", ", "");
@@ -1558,12 +1661,14 @@
 
         Node parent = node.getParentNode().orElse(null);
         if (parent == null) return;
-        List<Node> everything = new LinkedList<>();
-        everything.addAll(parent.getChildNodes());
+        List<Node> everything = new ArrayList<>(parent.getChildNodes());
         sortByBeginPosition(everything);
         int positionOfTheChild = -1;
-        for (int i = 0; i < everything.size(); i++) {
-            if (everything.get(i) == node) positionOfTheChild = i;
+        for (int i = 0; i < everything.size(); ++i) { // indexOf is by equality, so this is used to index by identity
+            if (everything.get(i) == node) {
+                positionOfTheChild = i;
+                break;
+            }
         }
         if (positionOfTheChild == -1) {
             throw new AssertionError("I am not a child of my parent.");
@@ -1585,8 +1690,7 @@
     private void printOrphanCommentsEnding(final Node node) {
         if (configuration.isIgnoreComments()) return;
 
-        List<Node> everything = new LinkedList<>();
-        everything.addAll(node.getChildNodes());
+        List<Node> everything = new ArrayList<>(node.getChildNodes());
         sortByBeginPosition(everything);
         if (everything.isEmpty()) {
             return;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinter.java b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinter.java
index 510457c..754153a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinter.java
@@ -22,6 +22,7 @@
 package com.github.javaparser.printer;
 
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.visitor.VoidVisitor;
 
 /**
  * Pretty printer for AST nodes.
@@ -38,8 +39,8 @@
     }
 
     public String print(Node node) {
-        final PrettyPrintVisitor visitor = configuration.getVisitorFactory().apply(configuration);
+        final VoidVisitor<Void> visitor = configuration.getVisitorFactory().apply(configuration);
         node.accept(visitor, null);
-        return visitor.getSource();
+        return visitor.toString();
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinterConfiguration.java b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinterConfiguration.java
index 1c650d2..0a6ccbb 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinterConfiguration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/PrettyPrinterConfiguration.java
@@ -21,36 +21,134 @@
 
 package com.github.javaparser.printer;
 
+import com.github.javaparser.ast.visitor.VoidVisitor;
+
 import java.util.function.Function;
 
+import static com.github.javaparser.printer.PrettyPrinterConfiguration.IndentType.SPACES;
 import static com.github.javaparser.utils.Utils.EOL;
+import static com.github.javaparser.utils.Utils.assertNonNegative;
 import static com.github.javaparser.utils.Utils.assertNotNull;
+import static com.github.javaparser.utils.Utils.assertPositive;
 
 /**
  * Configuration options for the {@link PrettyPrinter}.
  */
 public class PrettyPrinterConfiguration {
+    public enum IndentType {
+        /**
+         * Indent with spaces.
+         */
+        SPACES,
+
+        /**
+         * Indent with tabs as far as possible.
+         * For proper aligning, the tab width is necessary and by default 4.
+         */
+        TABS,
+
+        /**
+         * Indent with tabs but align with spaces when wrapping and aligning
+         * method call chains and method call parameters.
+         *
+         * <p/><i>Example result:</i>
+         * <pre>
+         * class Foo {
+         *
+         * \tvoid bar() {
+         * \t\tfoo().bar()
+         * \t\t......baz(() -> {
+         * \t\t..........\tboo().baa()
+         * \t\t..........\t......bee(a,
+         * \t\t..........\t..........b,
+         * \t\t..........\t..........c);
+         * \t\t..........})
+         * \t\t......bam();
+         * \t}
+         * }
+         * </pre>
+         */
+        TABS_WITH_SPACE_ALIGN
+    }
+
     public static final int DEFAULT_MAX_ENUM_CONSTANTS_TO_ALIGN_HORIZONTALLY = 5;
-    
+
     private boolean orderImports = false;
     private boolean printComments = true;
     private boolean printJavadoc = true;
     private boolean columnAlignParameters = false;
     private boolean columnAlignFirstMethodChain = false;
-    private String indent = "    ";
+    private IndentType indentType = SPACES;
+    private int tabWidth = 4;
+    private int indentSize = 4;
     private String endOfLineCharacter = EOL;
-    private Function<PrettyPrinterConfiguration, PrettyPrintVisitor> visitorFactory = PrettyPrintVisitor::new;
+    private Function<PrettyPrinterConfiguration, VoidVisitor<Void>> visitorFactory = PrettyPrintVisitor::new;
     private int maxEnumConstantsToAlignHorizontally = DEFAULT_MAX_ENUM_CONSTANTS_TO_ALIGN_HORIZONTALLY;
 
+    /**
+     * @return the string that will be used to indent.
+     */
     public String getIndent() {
-        return indent;
+        StringBuilder indentString = new StringBuilder();
+        char indentChar;
+        switch (indentType) {
+            case SPACES:
+                indentChar = ' ';
+                break;
+
+            case TABS:
+            case TABS_WITH_SPACE_ALIGN:
+                indentChar = '\t';
+                break;
+
+            default:
+                throw new AssertionError("Unhandled indent type");
+        }
+        for (int i = 0; i < indentSize; i++) {
+            indentString.append(indentChar);
+        }
+        return indentString.toString();
+    }
+
+    public int getIndentSize() {
+        return indentSize;
     }
 
     /**
-     * Set the string to use for indenting. For example: "\t", "    ", "".
+     * Set the size of the indent in characters.
      */
-    public PrettyPrinterConfiguration setIndent(String indent) {
-        this.indent = assertNotNull(indent);
+    public PrettyPrinterConfiguration setIndentSize(int indentSize) {
+        this.indentSize = assertNonNegative(indentSize);
+        return this;
+    }
+
+    /**
+     * Get the type of indent to produce.
+     */
+    public IndentType getIndentType() {
+        return indentType;
+    }
+
+    /**
+     * Set the type of indent to produce.
+     */
+    public PrettyPrinterConfiguration setIndentType(IndentType indentType) {
+        this.indentType = assertNotNull(indentType);
+        return this;
+    }
+
+    /**
+     * Get the tab width for pretty aligning.
+     */
+    public int getTabWidth() {
+        return tabWidth;
+    }
+
+    /**
+     * Set the tab width for pretty aligning.
+     */
+    public PrettyPrinterConfiguration setTabWidth(int tabWidth) {
+        this.tabWidth = assertPositive(tabWidth);
         return this;
     }
 
@@ -58,22 +156,6 @@
         return orderImports;
     }
 
-    /**
-     * @deprecated this is always on.
-     */
-    @Deprecated
-    public boolean isNormalizeEolInComment() {
-        return true;
-    }
-
-    /**
-     * @deprecated this is always on.
-     */
-    @Deprecated
-    public PrettyPrinterConfiguration setNormalizeEolInComment(boolean normalizeEolInComment) {
-        return this;
-    }
-
     public boolean isPrintComments() {
         return printComments;
     }
@@ -121,7 +203,7 @@
         return this;
     }
 
-    public Function<PrettyPrinterConfiguration, PrettyPrintVisitor> getVisitorFactory() {
+    public Function<PrettyPrinterConfiguration, VoidVisitor<Void>> getVisitorFactory() {
         return visitorFactory;
     }
 
@@ -129,7 +211,7 @@
      * Set the factory that creates the PrettyPrintVisitor. By changing this you can make the PrettyPrinter use a custom
      * PrettyPrinterVisitor.
      */
-    public PrettyPrinterConfiguration setVisitorFactory(Function<PrettyPrinterConfiguration, PrettyPrintVisitor> visitorFactory) {
+    public PrettyPrinterConfiguration setVisitorFactory(Function<PrettyPrinterConfiguration, VoidVisitor<Void>> visitorFactory) {
         this.visitorFactory = assertNotNull(visitorFactory);
         return this;
     }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/SourcePrinter.java b/javaparser-core/src/main/java/com/github/javaparser/printer/SourcePrinter.java
index a53d907..265378e 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/SourcePrinter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/SourcePrinter.java
@@ -22,72 +22,166 @@
 package com.github.javaparser.printer;
 
 import com.github.javaparser.Position;
+import com.github.javaparser.printer.PrettyPrinterConfiguration.IndentType;
 import com.github.javaparser.utils.Utils;
 
-public class SourcePrinter {
+import java.util.Deque;
+import java.util.LinkedList;
 
-    private final String indentation;
-    private final int indentationLength;
+import static com.github.javaparser.Position.*;
+
+/**
+ * A support class for code that outputs formatted source code.
+ */
+public class SourcePrinter {
     private final String endOfLineCharacter;
-    private int level = 0;
-    private boolean indented = false;
+    private final String indentation;
+    private final int tabWidth;
+    private final IndentType indentType;
+
+    private final Deque<String> indents = new LinkedList<>();
+    private final Deque<String> reindentedIndents = new LinkedList<>();
+    private String lastPrintedIndent = "";
     private final StringBuilder buf = new StringBuilder();
     private Position cursor = new Position(1, 0);
+    private boolean indented = false;
 
-    SourcePrinter(final String indentation, final String endOfLineCharacter) {
-        this.indentation = indentation;
-        this.indentationLength = indentation.length();
-        this.endOfLineCharacter = endOfLineCharacter;
+    SourcePrinter() {
+        this(new PrettyPrinterConfiguration());
     }
 
+    SourcePrinter(final PrettyPrinterConfiguration configuration) {
+        indentation = configuration.getIndent();
+        endOfLineCharacter = configuration.getEndOfLineCharacter();
+        tabWidth = configuration.getTabWidth();
+        indentType = configuration.getIndentType();
+        indents.push("");
+    }
+
+    /**
+     * Add the default indentation to the current indentation and push it on the indentation stack.
+     * Does not actually output anything.
+     */
     public SourcePrinter indent() {
-        level++;
-        return this;
-    }
+        String currentIndent = indents.peek();
+        switch (indentType) {
+            case SPACES:
+            case TABS_WITH_SPACE_ALIGN:
+                indents.push(currentIndent + indentation);
+                break;
 
-    public SourcePrinter unindent() {
-        level--;
-        return this;
-    }
+            case TABS:
+                indents.push(indentation + currentIndent);
+                break;
 
-    private void makeIndent() {
-        for (int i = 0; i < level; i++) {
-            buf.append(indentation);
-            cursor = Position.pos(cursor.line, cursor.column + indentationLength);
+            default:
+                throw new AssertionError("Unhandled indent type");
         }
+        return this;
+    }
+
+    /**
+     * Add to the current indentation until it is reaches "column" and push it on the indentation stack.
+     * Does not actually output anything.
+     */
+    public SourcePrinter indentWithAlignTo(int column) {
+        indents.push(calculateIndentWithAlignTo(column));
+        return this;
+    }
+
+    private String calculateIndentWithAlignTo(int column) {
+        if (column < lastPrintedIndent.length()){
+            throw new IllegalStateException("Attempt to indent less than the previous indent.");
+        }
+
+        StringBuilder newIndent = new StringBuilder(lastPrintedIndent);
+        switch (indentType) {
+            case SPACES:
+            case TABS_WITH_SPACE_ALIGN:
+                while (newIndent.length() < column) {
+                    newIndent.append(' ');
+                }
+                break;
+
+            case TABS:
+                int logicalIndentLength = newIndent.length();
+                while ((logicalIndentLength + tabWidth) <= column) {
+                    newIndent.insert(0, '\t');
+                    logicalIndentLength += tabWidth;
+                }
+                while (logicalIndentLength < column) {
+                    newIndent.append(' ');
+                    logicalIndentLength++;
+                }
+                StringBuilder fullTab = new StringBuilder();
+                for(int i=0; i<tabWidth; i++){
+                    fullTab.append(' ');
+                }
+                String fullTabString = fullTab.toString();
+                if ((newIndent.length() >= tabWidth)
+                        && newIndent.substring(newIndent.length() - tabWidth).equals(fullTabString)) {
+                    int i = newIndent.indexOf(fullTabString);
+                    newIndent.replace(i, i + tabWidth, "\t");
+                }
+                break;
+
+            default:
+                throw new AssertionError("Unhandled indent type");
+        }
+
+        return newIndent.toString();
+    }
+
+    /**
+     * Pop the last indentation of the indentation stack.
+     * Does not actually output anything.
+     */
+    public SourcePrinter unindent() {
+        if (indents.isEmpty()) {
+            // Since we start out with an empty indent on the stack, this will only occur
+            // the second time we over-unindent.
+            throw new IllegalStateException("Indent/unindent calls are not well-balanced.");
+        }
+        indents.pop();
+        return this;
+    }
+
+    private void append(String arg) {
+        buf.append(arg);
+        cursor = cursor.withColumn(cursor.column + arg.length());
     }
 
     /**
      * Append the source string passed as argument to the buffer.
      * If this is being appended at the beginning of a line, performs indentation first.
-     * <p> 
+     * <p>
      * The source line to be printed should not contain newline/carriage-return characters;
      * use {@link #println(String)} to automatically append a newline at the end of the source string.
      * If the source line passed as argument contains newline/carriage-return characters would
-     * impredictably affect a correct computation of the current {@link #getCursor()} position. 
-     * 
-     * @see SourcePrinter#println(String) 
+     * impredictably affect a correct computation of the current {@link #getCursor()} position.
+     *
      * @param arg source line to be printed (should not contain newline/carriage-return characters)
      * @return this instance, for nesting calls to method as fluent interface
+     * @see SourcePrinter#println(String)
      */
     public SourcePrinter print(final String arg) {
         if (!indented) {
-            makeIndent();
+            lastPrintedIndent = indents.peek();
+            append(lastPrintedIndent);
             indented = true;
         }
-        buf.append(arg);
-        cursor = Position.pos(cursor.line, cursor.column + arg.length());
+        append(arg);
         return this;
     }
 
     /**
      * Append the source string passed as argument to the buffer, then append a newline.
      * If this is being appended at the beginning of a line, performs indentation first.
-     * <p>  
+     * <p>
      * The source line to be printed should not contain newline/carriage-return characters.
      * If the source line passed as argument contains newline/carriage-return characters would
-     * impredictably affect a correct computation of the current {@link #getCursor()} position. 
-     * 
+     * impredictably affect a correct computation of the current {@link #getCursor()} position.
+     *
      * @param arg source line to be printed (should not contain newline/carriage-return characters)
      * @return this instance, for nesting calls to method as fluent interface
      */
@@ -99,24 +193,24 @@
 
     /**
      * Append a newline to the buffer.
-     * 
+     *
      * @return this instance, for nesting calls to method as fluent interface
      */
     public SourcePrinter println() {
         buf.append(endOfLineCharacter);
-        cursor = Position.pos(cursor.line + 1, 0);
+        cursor = pos(cursor.line + 1, 0);
         indented = false;
         return this;
     }
 
     /**
      * Return the current cursor position (line, column) in the source printer buffer.
-     * <p> 
+     * <p>
      * Please notice in order to guarantee a correct computation of the cursor position,
      * this printer expect the contracts of the methods {@link #print(String)} and {@link #println(String)}
      * has been respected through all method calls, meaning the source string passed as argument to those method
      * calls did not contain newline/carriage-return characters.
-     * 
+     *
      * @return the current cursor position (line, column).
      */
     public Position getCursor() {
@@ -124,30 +218,58 @@
     }
 
     /**
-     * Performs a new line and indent, then prints enough space characters until aligned to the specified column.
-     * @param column the column to align to
+     * @return the currently printed source code.
+     * @deprecated use toString()
      */
-    public void wrapToColumn(int column) {
-        println();
-        if (!indented) {
-            makeIndent();
-            indented = true;
-        }
-        while ( cursor.column < column ) {
-            print(" ");
-        }
+    @Deprecated
+    public String getSource() {
+        return toString();
     }
 
-    public String getSource() {
+    /**
+     * @return the currently printed source code.
+     */
+    @Override
+    public String toString() {
         return buf.toString();
     }
 
-    @Override
-    public String toString() {
-        return getSource();
-    }
-
+    /**
+     * Changes all EOL characters in "content" to the EOL character this SourcePrinter is using.
+     */
     public String normalizeEolInTextBlock(String content) {
         return Utils.normalizeEolInTextBlock(content, endOfLineCharacter);
     }
+
+    /**
+     * Set the top-most indent to the column the cursor is currently in, can be undone with
+     * {@link #reindentToPreviousLevel()}. Does not actually output anything.
+     */
+    public void reindentWithAlignToCursor() {
+        String newIndent = calculateIndentWithAlignTo(cursor.column);
+        reindentedIndents.push(indents.pop());
+        indents.push(newIndent);
+    }
+
+    /**
+     * Set the top-most indent to the column the cursor was before the last {@link #reindentWithAlignToCursor()} call.
+     * Does not actually output anything.
+     */
+    public void reindentToPreviousLevel() {
+        if (reindentedIndents.isEmpty()) {
+            throw new IllegalStateException("Reindent calls are not well-balanced.");
+        }
+        indents.pop();
+        indents.push(reindentedIndents.pop());
+    }
+
+    /**
+     * Adds an indent to the top of the stack that is a copy of the current top indent.
+     * With this you announce "I'm going to indent the next line(s)" but not how far yet.
+     * Once you do know, you can pop this indent ("unindent") and indent to the right column.
+     * (Does not actually output anything.)
+     */
+    public void duplicateIndent() {
+        indents.push(indents.peek());
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/YamlPrinter.java b/javaparser-core/src/main/java/com/github/javaparser/printer/YamlPrinter.java
index 1e418f5..ddf5779 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/YamlPrinter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/YamlPrinter.java
@@ -1,101 +1,111 @@
-/*

- * 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.printer;

-

-import static com.github.javaparser.utils.Utils.assertNotNull;

-import static java.util.stream.Collectors.toList;

-

-import java.util.List;

-

-import com.github.javaparser.ast.Node;

-import com.github.javaparser.ast.NodeList;

-import com.github.javaparser.metamodel.NodeMetaModel;

-import com.github.javaparser.metamodel.PropertyMetaModel;

-

-/**

- * Outputs a YAML file containing the AST meant for inspecting it.

- */

-public class YamlPrinter {

-

-    private static final int NUM_SPACES_FOR_INDENT = 4;

-    private final boolean outputNodeType;

-

-    public YamlPrinter(boolean outputNodeType) {

-        this.outputNodeType = outputNodeType;

-    }

-

-    public String output(Node node) {

-        StringBuilder output = new StringBuilder();

-        output.append("---");

-        output(node, "root", 0, output);

-        output.append(System.lineSeparator() + "...");

-        return output.toString();

-    }

-

-    public void output(Node node, String name, int level, StringBuilder builder) {

-        assertNotNull(node);

-        NodeMetaModel metaModel = node.getMetaModel();

-        List<PropertyMetaModel> allPropertyMetaModels = metaModel.getAllPropertyMetaModels();

-        List<PropertyMetaModel> attributes = allPropertyMetaModels.stream().filter(PropertyMetaModel::isAttribute)

-                .filter(PropertyMetaModel::isSingular).collect(toList());

-        List<PropertyMetaModel> subNodes = allPropertyMetaModels.stream().filter(PropertyMetaModel::isNode)

-                .filter(PropertyMetaModel::isSingular).collect(toList());

-        List<PropertyMetaModel> subLists = allPropertyMetaModels.stream().filter(PropertyMetaModel::isNodeList)

-                .collect(toList());

-

-        if (outputNodeType)

-            builder.append(System.lineSeparator() + indent(level) + name + "(Type=" + metaModel.getTypeName() + "): ");

-        else

-            builder.append(System.lineSeparator() + indent(level) + name + ": ");

-

-        level++;

-        for (PropertyMetaModel a : attributes) {

-            builder.append(System.lineSeparator() + indent(level) + a.getName() + ": \""

-                    + a.getValue(node).toString() + "\"");

-        }

-

-        for (PropertyMetaModel sn : subNodes) {

-            Node nd = (Node) sn.getValue(node);

-            if (nd != null)

-                output(nd, sn.getName(), level, builder);

-        }

-

-        for (PropertyMetaModel sl : subLists) {

-            NodeList<? extends Node> nl = (NodeList<? extends Node>) sl.getValue(node);

-            if (nl != null && nl.isNonEmpty()) {

-                builder.append(System.lineSeparator() + indent(level) + sl.getName() + ": ");

-                String slName = sl.getName();

-                slName = slName.endsWith("s") ? slName.substring(0, sl.getName().length() - 1) : slName;

-                for (Node nd : nl)

-                    output(nd, "- " + slName, level + 1, builder);

-            }

-        }

-    }

-

-    private String indent(int level) {

-        StringBuilder sb = new StringBuilder();

-        for (int i = 0; i < level; i++)

-            for (int j = 0; j < NUM_SPACES_FOR_INDENT; j++)

-                sb.append(" ");

-        return sb.toString();

-    }

-}

+/*
+ * 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.printer;
+
+import static com.github.javaparser.utils.Utils.assertNotNull;
+import static java.util.stream.Collectors.toList;
+
+import java.util.List;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.metamodel.NodeMetaModel;
+import com.github.javaparser.metamodel.PropertyMetaModel;
+
+/**
+ * Outputs a YAML file containing the AST meant for inspecting it.
+ */
+public class YamlPrinter {
+
+    private static final int NUM_SPACES_FOR_INDENT = 4;
+    private final boolean outputNodeType;
+
+    public YamlPrinter(boolean outputNodeType) {
+        this.outputNodeType = outputNodeType;
+    }
+
+    public String output(Node node) {
+        StringBuilder output = new StringBuilder();
+        output.append("---");
+        output(node, "root", 0, output);
+        output.append(System.lineSeparator() + "...");
+        return output.toString();
+    }
+
+    public void output(Node node, String name, int level, StringBuilder builder) {
+        assertNotNull(node);
+        NodeMetaModel metaModel = node.getMetaModel();
+        List<PropertyMetaModel> allPropertyMetaModels = metaModel.getAllPropertyMetaModels();
+        List<PropertyMetaModel> attributes = allPropertyMetaModels.stream().filter(PropertyMetaModel::isAttribute)
+                .filter(PropertyMetaModel::isSingular).collect(toList());
+        List<PropertyMetaModel> subNodes = allPropertyMetaModels.stream().filter(PropertyMetaModel::isNode)
+                .filter(PropertyMetaModel::isSingular).collect(toList());
+        List<PropertyMetaModel> subLists = allPropertyMetaModels.stream().filter(PropertyMetaModel::isNodeList)
+                .collect(toList());
+
+        if (outputNodeType)
+            builder.append(System.lineSeparator() + indent(level) + name + "(Type=" + metaModel.getTypeName() + "): ");
+        else
+            builder.append(System.lineSeparator() + indent(level) + name + ": ");
+
+        level++;
+        for (PropertyMetaModel a : attributes) {
+            builder.append(System.lineSeparator() + indent(level) + a.getName() + ": " + escapeValue(a.getValue(node).toString()));
+        }
+
+        for (PropertyMetaModel sn : subNodes) {
+            Node nd = (Node) sn.getValue(node);
+            if (nd != null)
+                output(nd, sn.getName(), level, builder);
+        }
+
+        for (PropertyMetaModel sl : subLists) {
+            NodeList<? extends Node> nl = (NodeList<? extends Node>) sl.getValue(node);
+            if (nl != null && nl.isNonEmpty()) {
+                builder.append(System.lineSeparator() + indent(level) + sl.getName() + ": ");
+                String slName = sl.getName();
+                slName = slName.endsWith("s") ? slName.substring(0, sl.getName().length() - 1) : slName;
+                for (Node nd : nl)
+                    output(nd, "- " + slName, level + 1, builder);
+            }
+        }
+    }
+
+    private String indent(int level) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < level; i++)
+            for (int j = 0; j < NUM_SPACES_FOR_INDENT; j++)
+                sb.append(" ");
+        return sb.toString();
+    }
+
+    private String escapeValue(String value) {
+        return "\"" + value
+                .replace("\\", "\\\\")
+                .replaceAll("\"", "\\\\\"")
+                .replace("\n", "\\n")
+                .replace("\r", "\\r")
+                .replace("\f", "\\f")
+                .replace("\b", "\\b")
+                .replace("\t", "\\t") + "\"";
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmAttribute.java b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmAttribute.java
index b44672d..2f898d0 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmAttribute.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmAttribute.java
@@ -27,6 +27,8 @@
 import com.github.javaparser.ast.observer.ObservableProperty;
 import com.github.javaparser.printer.SourcePrinter;
 
+import static com.github.javaparser.utils.CodeGenerationUtils.f;
+
 public class CsmAttribute implements CsmElement {
     public ObservableProperty getProperty() {
         return property;
@@ -47,25 +49,32 @@
     /**
      * Obtain the token type corresponding to the specific value of the attribute.
      * For example, to the attribute "Operator" different token could correspond like PLUS or MINUS.
+     *
+     * @param tokenText Operator's token text
      */
-    public int getTokenType(Node node, String text) {
+    public int getTokenType(Node node, String text, String tokenText) {
         switch (property) {
             case IDENTIFIER:
                 return GeneratedJavaParserConstants.IDENTIFIER;
-            case TYPE:
+            case TYPE: {
                 String expectedImage = "\"" + text.toLowerCase() + "\"";
                 for (int i=0;i<GeneratedJavaParserConstants.tokenImage.length;i++) {
                     if (GeneratedJavaParserConstants.tokenImage[i].equals(expectedImage)) {
                         return i;
                     }
                 }
-                throw new RuntimeException("Attribute 'type' does not corresponding to any expected value. Text: " + text);
-            case OPERATOR:
-                try {
-                    return (Integer)(GeneratedJavaParserConstants.class.getDeclaredField(text).get(null));
-                } catch (IllegalAccessException|NoSuchFieldException e) {
-                    throw new RuntimeException("Attribute 'operator' does not corresponding to any expected value. Text: " + text, e);
+                throw new RuntimeException(f("Attribute '%s' does not corresponding to any expected value. Text: %s", property.camelCaseName(), text));
+            }
+            case KEYWORD:
+            case OPERATOR: {
+                String expectedImage = "\"" + tokenText.toLowerCase() + "\"";
+                for (int i = 0; i < GeneratedJavaParserConstants.tokenImage.length; i++) {
+                    if (GeneratedJavaParserConstants.tokenImage[i].equals(expectedImage)) {
+                        return i;
+                    }
                 }
+                throw new RuntimeException(f("Attribute '%s' does not corresponding to any expected value. Text: %s", property.camelCaseName(), tokenText));
+            }
             case VALUE:
                 if (node instanceof IntegerLiteralExpr) {
                     return GeneratedJavaParserConstants.INTEGER_LITERAL;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmConditional.java b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmConditional.java
index a2ca7cd..2db3be8 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmConditional.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmConditional.java
@@ -45,6 +45,10 @@
         }
         return properties.get(0);
     }
+    
+    public List<ObservableProperty> getProperties() {
+        return properties;
+    }
 
     public CsmElement getThenElement() {
         return thenElement;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmMix.java b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmMix.java
index 9ce5461..a2c5d25 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmMix.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmMix.java
@@ -49,6 +49,6 @@
 
     @Override
     public String toString() {
-        return "CsmMix[" + String.join(", ", elements.stream().map(e -> elements.toString()).collect(Collectors.toList())) + "]";
+        return elements.stream().map(e -> e.toString()).collect(Collectors.joining(",", "CsmMix[", "]"));
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Added.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Added.java
new file mode 100644
index 0000000..5b5857d
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Added.java
@@ -0,0 +1,63 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmIndent;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmUnindent;
+
+public class Added implements DifferenceElement {
+    private final CsmElement element;
+
+    Added(CsmElement element) {
+        this.element = element;
+    }
+
+    @Override
+    public String toString() {
+        return "Added{" + element + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Added added = (Added) o;
+
+        return element.equals(added.element);
+    }
+
+    @Override
+    public int hashCode() {
+        return element.hashCode();
+    }
+
+    @Override
+    public CsmElement getElement() {
+        return element;
+    }
+
+    @Override
+    public boolean isAdded() {
+        return true;
+    }
+
+    @Override
+    public boolean isRemoved() {
+        return false;
+    }
+
+    public boolean isIndent() { return element instanceof CsmIndent; }
+
+    public boolean isUnindent() { return element instanceof CsmUnindent; }
+
+    public TextElement toTextElement() {
+        if (element instanceof LexicalDifferenceCalculator.CsmChild) {
+            return new ChildTextElement(((LexicalDifferenceCalculator.CsmChild) element).getChild());
+        } else if (element instanceof CsmToken) {
+            return new TokenTextElement(((CsmToken) element).getTokenType(), ((CsmToken) element).getContent(null));
+        } else {
+            throw new UnsupportedOperationException(element.getClass().getSimpleName());
+        }
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java
index ad890c4..9131c8a 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/ChildTextElement.java
@@ -21,9 +21,12 @@
 
 package com.github.javaparser.printer.lexicalpreservation;
 
+import com.github.javaparser.Range;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.comments.Comment;
 
+import java.util.Optional;
+
 /**
  * Represent the position of a child node in the NodeText of its parent.
  */
@@ -101,4 +104,9 @@
     public boolean isChildOfClass(Class<? extends Node> nodeClass) {
         return nodeClass.isInstance(child);
     }
+
+    @Override
+    Optional<Range> getRange() {
+        return child.getRange();
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java
index 610f916..b76a37d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Difference.java
@@ -1,17 +1,19 @@
 package com.github.javaparser.printer.lexicalpreservation;
 
-import com.github.javaparser.GeneratedJavaParserConstants;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.comments.Comment;
-import com.github.javaparser.ast.type.PrimitiveType;
-import com.github.javaparser.TokenTypes;
-import com.github.javaparser.printer.concretesyntaxmodel.*;
-import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild;
+import static com.github.javaparser.GeneratedJavaParserConstants.*;
 
 import java.util.*;
-import java.util.stream.Collectors;
 
-import static com.github.javaparser.GeneratedJavaParserConstants.*;
+import com.github.javaparser.GeneratedJavaParserConstants;
+import com.github.javaparser.TokenTypes;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.comments.Comment;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmIndent;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmMix;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmUnindent;
+import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild;
 
 /**
  * A Difference should give me a sequence of elements I should find (to indicate the context) followed by a list of elements
@@ -21,396 +23,37 @@
  */
 public class Difference {
 
-    private static final int STANDARD_INDENTATION_SIZE = 4;
+    public static final int STANDARD_INDENTATION_SIZE = 4;
 
-    private final List<DifferenceElement> elements;
+    private final NodeText nodeText;
+    private final Node node;
 
-    private Difference(List<DifferenceElement> elements) {
-        this.elements = elements;
-    }
+    private final List<DifferenceElement> diffElements;
+    private final List<TextElement> originalElements;
+    private int originalIndex = 0;
+    private int diffIndex = 0;
 
-    interface DifferenceElement {
-        static DifferenceElement added(CsmElement element) {
-            return new Added(element);
+    private final List<TokenTextElement> indentation;
+    private boolean addedIndentation = false;
+
+    Difference(List<DifferenceElement> diffElements, NodeText nodeText, Node node) {
+        if (nodeText == null) {
+            throw new NullPointerException("nodeText can not be null");
         }
 
-        static DifferenceElement removed(CsmElement element) {
-            return new Removed(element);
-        }
+        this.nodeText = nodeText;
+        this.node = node;
+        this.diffElements = diffElements;
+        this.originalElements = nodeText.getElements();
 
-        static DifferenceElement kept(CsmElement element) {
-            return new Kept(element);
-        }
-
-        /**
-         * Return the CsmElement considered in this DifferenceElement.
-         */
-        CsmElement getElement();
-
-        boolean isAdded();
-    }
-
-    private static class Added implements DifferenceElement {
-        final CsmElement element;
-
-        public Added(CsmElement element) {
-            this.element = element;
-        }
-
-        @Override
-        public String toString() {
-            return "Added{" + element + '}';
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Added added = (Added) o;
-
-            return element.equals(added.element);
-        }
-
-        @Override
-        public int hashCode() {
-            return element.hashCode();
-        }
-
-        @Override
-        public CsmElement getElement() {
-            return element;
-        }
-
-        @Override
-        public boolean isAdded() {
-            return true;
-        }
-    }
-
-    /**
-     * Elements in a CsmMix have been reshuffled. It could also mean that
-     * some new elements have been added or removed to the mix.
-     */
-    private static class Reshuffled implements DifferenceElement {
-        final CsmMix previousOrder;
-        final CsmMix element;
-
-        public Reshuffled(CsmMix previousOrder, CsmMix element) {
-            this.previousOrder = previousOrder;
-            this.element = element;
-        }
-
-        @Override
-        public String toString() {
-            return "Reshuffled{" + element + ", previous="+ previousOrder+ '}';
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Reshuffled that = (Reshuffled) o;
-
-            if (!previousOrder.equals(that.previousOrder)) return false;
-            return element.equals(that.element);
-        }
-
-        @Override
-        public int hashCode() {
-            int result = previousOrder.hashCode();
-            result = 31 * result + element.hashCode();
-            return result;
-        }
-
-        @Override
-        public CsmMix getElement() {
-            return element;
-        }
-
-        @Override
-        public boolean isAdded() {
-            return false;
-        }
-    }
-
-    private static class Kept implements DifferenceElement {
-        final CsmElement element;
-
-        public Kept(CsmElement element) {
-            this.element = element;
-        }
-
-        @Override
-        public String toString() {
-            return "Kept{" + element + '}';
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Kept kept = (Kept) o;
-
-            return element.equals(kept.element);
-        }
-
-        @Override
-        public int hashCode() {
-            return element.hashCode();
-        }
-
-        @Override
-        public CsmElement getElement() {
-            return element;
-        }
-
-        @Override
-        public boolean isAdded() {
-            return false;
-        }
-    }
-
-    private static class Removed implements DifferenceElement {
-        final CsmElement element;
-
-        public Removed(CsmElement element) {
-            this.element = element;
-        }
-
-        @Override
-        public String toString() {
-            return "Removed{" + element + '}';
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Removed removed = (Removed) o;
-
-            return element.equals(removed.element);
-        }
-
-        @Override
-        public int hashCode() {
-            return element.hashCode();
-        }
-
-        @Override
-        public CsmElement getElement() {
-            return element;
-        }
-
-        @Override
-        public boolean isAdded() {
-            return false;
-        }
-    }
-
-    private static boolean matching(CsmElement a, CsmElement b) {
-        if (a instanceof CsmChild) {
-            if (b instanceof CsmChild) {
-                CsmChild childA = (CsmChild) a;
-                CsmChild childB = (CsmChild) b;
-                return childA.getChild().equals(childB.getChild());
-            } else if (b instanceof CsmToken) {
-                return false;
-            } else if (b instanceof CsmIndent) {
-                return false;
-            } else if (b instanceof CsmUnindent) {
-                return false;
-            } else {
-                throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
-            }
-        } else if (a instanceof CsmToken) {
-            if (b instanceof CsmToken) {
-                CsmToken childA = (CsmToken)a;
-                CsmToken childB = (CsmToken)b;
-                return childA.getTokenType() == childB.getTokenType();
-            } else if (b instanceof CsmChild) {
-                return false;
-            } else if (b instanceof CsmIndent) {
-                return false;
-            } else if (b instanceof CsmUnindent) {
-                return false;
-            } else {
-                throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
-            }
-        } else if (a instanceof CsmIndent) {
-            return b instanceof CsmIndent;
-        } else if (a instanceof CsmUnindent) {
-            return b instanceof CsmUnindent;
-        }
-        throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
-    }
-
-    private static boolean replacement(CsmElement a, CsmElement b) {
-        if (a instanceof CsmIndent || b instanceof CsmIndent || a instanceof CsmUnindent || b instanceof CsmUnindent) {
-            return false;
-        }
-        if (a instanceof CsmChild) {
-            if (b instanceof CsmChild) {
-                CsmChild childA = (CsmChild) a;
-                CsmChild childB = (CsmChild) b;
-                return childA.getChild().getClass().equals(childB.getChild().getClass());
-            } else if (b instanceof CsmToken) {
-                return false;
-            } else {
-                throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
-            }
-        } else if (a instanceof CsmToken) {
-            if (b instanceof CsmToken) {
-                CsmToken childA = (CsmToken)a;
-                CsmToken childB = (CsmToken)b;
-                return childA.getTokenType() == childB.getTokenType();
-            } else if (b instanceof CsmChild) {
-                return false;
-            }
-        }
-        throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
-    }
-
-    /**
-     * Find the positions of all the given children.
-     */
-    private static Map<Node, Integer> findChildrenPositions(LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel) {
-        Map<Node, Integer> positions = new HashMap<>();
-        for (int i=0;i<calculatedSyntaxModel.elements.size();i++) {
-            CsmElement element = calculatedSyntaxModel.elements.get(i);
-            if (element instanceof CsmChild) {
-                positions.put(((CsmChild)element).getChild(), i);
-            }
-        }
-        return positions;
-    }
-
-    /**
-     * Calculate the Difference between two CalculatedSyntaxModel elements, determining which elements were kept,
-     * which were added and which were removed.
-     */
-    static Difference calculate(LexicalDifferenceCalculator.CalculatedSyntaxModel original, LexicalDifferenceCalculator.CalculatedSyntaxModel after) {
-        // For performance reasons we use the positions of matching children
-        // to guide the calculation of the difference
-        //
-        // Suppose we have:
-        //   qwerty[A]uiop
-        //   qwer[A]uiop
-        //
-        // with [A] being a child and lowercase letters being tokens
-        //
-        // We would calculate the Difference between "qwerty" and "qwer" then we know the A is kep, and then we
-        // would calculate the difference between "uiop" and "uiop"
-
-        Map<Node, Integer> childrenInOriginal = findChildrenPositions(original);
-        Map<Node, Integer> childrenInAfter = findChildrenPositions(after);
-
-        List<Node> commonChildren = new LinkedList<>(childrenInOriginal.keySet());
-        commonChildren.retainAll(childrenInAfter.keySet());
-        commonChildren.sort(Comparator.comparingInt(childrenInOriginal::get));
-
-        List<DifferenceElement> elements = new LinkedList<>();
-
-        int originalIndex = 0;
-        int afterIndex = 0;
-        int commonChildrenIndex = 0;
-        while (commonChildrenIndex < commonChildren.size()) {
-            Node child = commonChildren.get(commonChildrenIndex++);
-            int posOfNextChildInOriginal = childrenInOriginal.get(child);
-            int posOfNextChildInAfter    = childrenInAfter.get(child);
-            if (originalIndex < posOfNextChildInOriginal || afterIndex < posOfNextChildInAfter) {
-                elements.addAll(calculateImpl(original.sub(originalIndex, posOfNextChildInOriginal), after.sub(afterIndex, posOfNextChildInAfter)).elements);
-            }
-            elements.add(new Kept(new CsmChild(child)));
-            originalIndex = posOfNextChildInOriginal + 1;
-            afterIndex = posOfNextChildInAfter + 1;
-        }
-
-        if (originalIndex < original.elements.size() || afterIndex < after.elements.size()) {
-            elements.addAll(calculateImpl(original.sub(originalIndex, original.elements.size()), after.sub(afterIndex, after.elements.size())).elements);
-        }
-        return new Difference(elements);
-    }
-
-    private static Difference calculateImpl(LexicalDifferenceCalculator.CalculatedSyntaxModel original, LexicalDifferenceCalculator.CalculatedSyntaxModel after) {
-        List<DifferenceElement> elements = new LinkedList<>();
-
-        int originalIndex = 0;
-        int afterIndex = 0;
-
-        // We move through the two CalculatedSyntaxModel, moving both forward when we have a match
-        // and moving just one side forward when we have an element kept or removed
-
-        do {
-            if (originalIndex < original.elements.size() && afterIndex >= after.elements.size()) {
-                elements.add(new Removed(original.elements.get(originalIndex)));
-                originalIndex++;
-            } else if (originalIndex >= original.elements.size() && afterIndex < after.elements.size()) {
-                elements.add(new Added(after.elements.get(afterIndex)));
-                afterIndex++;
-            } else {
-                CsmElement nextOriginal = original.elements.get(originalIndex);
-                CsmElement nextAfter = after.elements.get(afterIndex);
-
-                if ((nextOriginal instanceof CsmMix) && (nextAfter instanceof CsmMix)) {
-                    if (((CsmMix) nextAfter).getElements().equals(((CsmMix) nextOriginal).getElements())) {
-                        // No reason to deal with a reshuffled, we are just going to keep everything as it is
-                        ((CsmMix) nextAfter).getElements().forEach(el -> elements.add(new Kept(el)));
-                    } else {
-                        elements.add(new Reshuffled((CsmMix)nextOriginal, (CsmMix)nextAfter));
-                    }
-                    originalIndex++;
-                    afterIndex++;
-                } else if (matching(nextOriginal, nextAfter)) {
-                    elements.add(new Kept(nextOriginal));
-                    originalIndex++;
-                    afterIndex++;
-                } else if (replacement(nextOriginal, nextAfter)) {
-                    elements.add(new Removed(nextOriginal));
-                    elements.add(new Added(nextAfter));
-                    originalIndex++;
-                    afterIndex++;
-                } else {
-                    // We can try to remove the element or add it and look which one leads to the lower difference
-                    Difference adding = calculate(original.from(originalIndex), after.from(afterIndex + 1));
-                    Difference removing = null;
-                    if (adding.cost() > 0) {
-                        removing = calculate(original.from(originalIndex + 1), after.from(afterIndex));
-                    }
-
-                    if (removing == null || removing.cost() > adding.cost()) {
-                        elements.add(new Added(nextAfter));
-                        afterIndex++;
-                    } else {
-                        elements.add(new Removed(nextOriginal));
-                        originalIndex++;
-                    }
-                }
-            }
-        } while (originalIndex < original.elements.size() || afterIndex < after.elements.size());
-
-        return new Difference(elements);
-    }
-
-    private TextElement toTextElement(CsmElement csmElement) {
-        if (csmElement instanceof CsmChild) {
-            return new ChildTextElement(((CsmChild) csmElement).getChild());
-        } else if (csmElement instanceof CsmToken) {
-            return new TokenTextElement(((CsmToken) csmElement).getTokenType(), ((CsmToken) csmElement).getContent(null));
-        } else {
-            throw new UnsupportedOperationException(csmElement.getClass().getSimpleName());
-        }
+        this.indentation = LexicalPreservingPrinter.findIndentation(node);
     }
 
     private List<TextElement> processIndentation(List<TokenTextElement> indentation, List<TextElement> prevElements) {
-        List<TextElement> res = new LinkedList<>();
-        res.addAll(indentation);
+        List<TextElement> res = new LinkedList<>(indentation);
         boolean afterNl = false;
         for (TextElement e : prevElements) {
-            if (e.isNewline() || e.isToken(SINGLE_LINE_COMMENT)) {
+            if (e.isNewline()) {
                 res.clear();
                 afterNl = true;
             } else {
@@ -433,19 +76,11 @@
         return res;
     }
 
-    private int considerCleaningTheLine(NodeText nodeText, int nodeTextIndex) {
-        while (nodeTextIndex >=1 && nodeText.getElements().get(nodeTextIndex - 1).isWhiteSpace() && !nodeText.getElements().get(nodeTextIndex - 1).isNewline()) {
-            nodeText.removeElement(nodeTextIndex - 1);
-            nodeTextIndex--;
-        }
-        return nodeTextIndex;
-    }
-
     private boolean isAfterLBrace(NodeText nodeText, int nodeTextIndex) {
         if (nodeTextIndex > 0 && nodeText.getElements().get(nodeTextIndex - 1).isToken(LBRACE)) {
             return true;
         }
-        if (nodeTextIndex > 0 && nodeText.getElements().get(nodeTextIndex - 1).isWhiteSpace() && !nodeText.getElements().get(nodeTextIndex - 1).isNewline()) {
+        if (nodeTextIndex > 0 && nodeText.getElements().get(nodeTextIndex - 1).isSpaceOrTab()) {
             return isAfterLBrace(nodeText, nodeTextIndex - 1);
         }
         return false;
@@ -457,7 +92,7 @@
      */
     private int considerEnforcingIndentation(NodeText nodeText, int nodeTextIndex) {
         boolean hasOnlyWsBefore = true;
-        for (int i=nodeTextIndex; i >= 0 && hasOnlyWsBefore && i < nodeText.getElements().size(); i--) {
+        for (int i = nodeTextIndex; i >= 0 && hasOnlyWsBefore && i < nodeText.getElements().size(); i--) {
             if (nodeText.getElements().get(i).isNewline()) {
                 break;
             }
@@ -465,364 +100,652 @@
                 hasOnlyWsBefore = false;
             }
         }
+        int res = nodeTextIndex;
         if (hasOnlyWsBefore) {
-            for (int i=nodeTextIndex; i >= 0 && i < nodeText.getElements().size(); i--) {
+            for (int i = nodeTextIndex; i >= 0 && i < nodeText.getElements().size(); i--) {
                 if (nodeText.getElements().get(i).isNewline()) {
                     break;
                 }
                 nodeText.removeElement(i);
+                res = i;
             }
         }
-        return nodeTextIndex;
+        if (res < 0) {
+            throw new IllegalStateException();
+        }
+        return res;
     }
 
     /**
      * Node that we have calculate the Difference we can apply to a concrete NodeText, modifying it according
      * to the difference (adding and removing the elements provided).
      */
-    void apply(NodeText nodeText, Node node) {
-        if (nodeText == null) {
-            throw new NullPointerException();
-        }
-        boolean addedIndentation = false;
-        List<TokenTextElement> indentation = LexicalPreservingPrinter.findIndentation(node);
-        int diffIndex = 0;
-        int nodeTextIndex = 0;
+    void apply() {
+        extractReshuffledDiffElements(diffElements);
+        Map<Removed, RemovedGroup> removedGroups = combineRemovedElementsToRemovedGroups();
+
         do {
-            if (diffIndex < this.elements.size() && nodeTextIndex >= nodeText.getElements().size()) {
-                DifferenceElement diffEl = elements.get(diffIndex);
-                if (diffEl instanceof Kept) {
-                    Kept kept = (Kept) diffEl;
-                    if (kept.element instanceof CsmToken) {
-                        CsmToken csmToken = (CsmToken) kept.element;
-                        if (TokenTypes.isWhitespaceOrComment(csmToken.getTokenType())) {
-                            diffIndex++;
-                        } else {
-                            throw new IllegalStateException("Cannot keep element because we reached the end of nodetext: "
-                                    + nodeText + ". Difference: " + this);
-                        }
-                    } else {
-                        throw new IllegalStateException("Cannot keep element because we reached the end of nodetext: "
-                                + nodeText + ". Difference: " + this);
-                    }
-                } else if (diffEl instanceof Added) {
-                    nodeText.addElement(nodeTextIndex, toTextElement(((Added) diffEl).element));
-                    nodeTextIndex++;
-                    diffIndex++;
+            boolean isLeftOverDiffElement = applyLeftOverDiffElements();
+            boolean isLeftOverOriginalElement = applyLeftOverOriginalElements();
+
+            if (!isLeftOverDiffElement && !isLeftOverOriginalElement){
+                DifferenceElement diffElement = diffElements.get(diffIndex);
+
+                if (diffElement instanceof Added) {
+                    applyAddedDiffElement((Added) diffElement);
                 } else {
-                    throw new UnsupportedOperationException(diffEl.getClass().getSimpleName());
-                }
-            } else if (diffIndex >= this.elements.size() && nodeTextIndex < nodeText.getElements().size()) {
-                TextElement nodeTextEl = nodeText.getElements().get(nodeTextIndex);
-                if (nodeTextEl.isWhiteSpaceOrComment()) {
-                    nodeTextIndex++;
-                } else {
-                    throw new UnsupportedOperationException("NodeText: " + nodeText + ". Difference: "
-                            + this + " " + nodeTextEl);
-                }
-            } else {
-                DifferenceElement diffEl = elements.get(diffIndex);
-                TextElement nodeTextEl = nodeText.getElements().get(nodeTextIndex);
-                if (diffEl instanceof Added) {
-                    CsmElement addedElement = ((Added) diffEl).element;
-                    if (addedElement instanceof CsmIndent) {
-                        for (int i=0;i<STANDARD_INDENTATION_SIZE;i++){
-                            indentation.add(new TokenTextElement(GeneratedJavaParserConstants.SPACE));
-                        }
-                        addedIndentation = true;
-                        diffIndex++;
-                        continue;
-                    }
-                    if (addedElement instanceof CsmUnindent) {
-                        for (int i=0;i<STANDARD_INDENTATION_SIZE && !indentation.isEmpty();i++){
-                            indentation.remove(indentation.size() - 1);
-                        }
-                        addedIndentation = false;
-                        diffIndex++;
-                        continue;
-                    }
-                    TextElement textElement = toTextElement(addedElement);
-                    boolean used = false;
-                    if (nodeTextIndex > 0 && nodeText.getElements().get(nodeTextIndex - 1).isNewline()) {
-                        for (TextElement e : processIndentation(indentation, nodeText.getElements().subList(0, nodeTextIndex - 1))) {
-                            nodeText.addElement(nodeTextIndex++, e);
-                        }
-                    } else if (isAfterLBrace(nodeText, nodeTextIndex) && !isAReplacement(diffIndex)) {
-                        if (textElement.isNewline()) {
-                            used = true;
-                        }
-                        nodeText.addElement(nodeTextIndex++, new TokenTextElement(TokenTypes.eolTokenKind()));
-                        // This remove the space in "{ }" when adding a new line
-                        while (nodeText.getElements().get(nodeTextIndex).isSpaceOrTab()) {
-                            nodeText.getElements().remove(nodeTextIndex);
-                        }
-                        for (TextElement e : processIndentation(indentation, nodeText.getElements().subList(0, nodeTextIndex - 1))) {
-                            nodeText.addElement(nodeTextIndex++, e);
-                        }
-                        // Indentation is painful...
-                        // Sometimes we want to force indentation: this is the case when indentation was expected but
-                        // was actually not there. For example if we have "{ }" we would expect indentation but it is
-                        // not there, so when adding new elements we force it. However if the indentation has been
-                        // inserted by us in this transformation we do not want to insert it again
-                        if (!addedIndentation) {
-                            for (TextElement e : indentationBlock()) {
-                                nodeText.addElement(nodeTextIndex++, e);
-                            }
-                        }
-                    }
-                    if (!used) {
-                        nodeText.addElement(nodeTextIndex, textElement);
-                        nodeTextIndex++;
-                    }
-                    if (textElement.isNewline()) {
-                        boolean followedByUnindent = (diffIndex + 1) < elements.size()
-                                && elements.get(diffIndex + 1).isAdded()
-                                && elements.get(diffIndex + 1).getElement() instanceof CsmUnindent;
-                        nodeTextIndex = adjustIndentation(indentation, nodeText, nodeTextIndex, followedByUnindent/* && !addedIndentation*/);
-                    }
-                    diffIndex++;
-                } else if (diffEl instanceof Kept) {
-                    Kept kept = (Kept)diffEl;
-                    if (nodeTextEl.isComment()) {
-                        nodeTextIndex++;
-                    } else if ((kept.element instanceof CsmChild) && nodeTextEl instanceof ChildTextElement) {
-                        diffIndex++;
-                        nodeTextIndex++;
-                    } else if ((kept.element instanceof CsmChild) && nodeTextEl instanceof TokenTextElement) {
-                        if (nodeTextEl.isWhiteSpaceOrComment()) {
-                            nodeTextIndex++;
-                        } else {
-                            if (kept.element instanceof CsmChild) {
-                                CsmChild keptChild = (CsmChild)kept.element;
-                                if (keptChild.getChild() instanceof PrimitiveType) {
-                                    nodeTextIndex++;
-                                    diffIndex++;
-                                } else {
-                                    throw new UnsupportedOperationException("kept " + kept.element + " vs " + nodeTextEl);
-                                }
-                            } else {
-                                throw new UnsupportedOperationException("kept " + kept.element + " vs " + nodeTextEl);
-                            }
-                        }
-                    } else if ((kept.element instanceof CsmToken) && nodeTextEl instanceof TokenTextElement) {
-                        CsmToken csmToken = (CsmToken) kept.element;
-                        TokenTextElement nodeTextToken = (TokenTextElement) nodeTextEl;
-                        if (csmToken.getTokenType() == nodeTextToken.getTokenKind()) {
-                            nodeTextIndex++;
-                            diffIndex++;
-                        } else if (TokenTypes.isWhitespaceOrComment(csmToken.getTokenType())) {
-                            diffIndex++;
-                        } else if (nodeTextToken.isWhiteSpaceOrComment()) {
-                            nodeTextIndex++;
-                        } else {
-                            throw new UnsupportedOperationException("Csm token " + csmToken + " NodeText TOKEN " + nodeTextToken);
-                        }
-                    } else if ((kept.element instanceof CsmToken) && ((CsmToken) kept.element).isWhiteSpace()) {
-                        diffIndex++;
-                    } else if (kept.element instanceof CsmIndent) {
-                        // Nothing to do
-                        diffIndex++;
-                    } else if (kept.element instanceof CsmUnindent) {
-                        // Nothing to do, beside considering indentation
-                        diffIndex++;
-                        for (int i = 0; i < STANDARD_INDENTATION_SIZE && nodeTextIndex >= 1 && nodeText.getTextElement(nodeTextIndex - 1).isSpaceOrTab(); i++) {
-                            nodeText.removeElement(--nodeTextIndex);
-                        }
+                    TextElement originalElement = originalElements.get(originalIndex);
+                    boolean originalElementIsChild = originalElement instanceof ChildTextElement;
+                    boolean originalElementIsToken = originalElement instanceof TokenTextElement;
+
+                    if (diffElement instanceof Kept) {
+                        applyKeptDiffElement((Kept) diffElement, originalElement, originalElementIsChild, originalElementIsToken);
+                    } else if (diffElement instanceof Removed) {
+                        Removed removed = (Removed) diffElement;
+                        applyRemovedDiffElement(removedGroups.get(removed), removed, originalElement, originalElementIsChild, originalElementIsToken);
                     } else {
-                        throw new UnsupportedOperationException("kept " + kept.element + " vs " + nodeTextEl);
+                        throw new UnsupportedOperationException("" + diffElement + " vs " + originalElement);
                     }
-                } else if (diffEl instanceof Removed) {
-                    Removed removed = (Removed)diffEl;
-                    if ((removed.element instanceof CsmChild) && nodeTextEl instanceof ChildTextElement) {
-                        ChildTextElement actualChild = (ChildTextElement)nodeTextEl;
-                        if (actualChild.isComment()) {
-                            CsmChild csmChild = (CsmChild)removed.element;
-                            // We expected to remove a proper node but we found a comment in between.
-                            // If the comment is associated to the node we want to remove we remove it as well, otherwise we keep it
-                            Comment comment = (Comment)actualChild.getChild();
-                            if (!comment.isOrphan() && comment.getCommentedNode().isPresent() && comment.getCommentedNode().get().equals(csmChild.getChild())) {
-                                nodeText.removeElement(nodeTextIndex);
-                            } else {
-                                nodeTextIndex++;
-                            }
-                        } else {
-                            nodeText.removeElement(nodeTextIndex);
-                            if (nodeTextIndex < nodeText.getElements().size() && nodeText.getElements().get(nodeTextIndex).isNewline()) {
-                                nodeTextIndex = considerCleaningTheLine(nodeText, nodeTextIndex);
-                            } else {
-                                if (diffIndex + 1 >= this.getElements().size() || !(this.getElements().get(diffIndex + 1) instanceof Added)) {
-                                    nodeTextIndex = considerEnforcingIndentation(nodeText, nodeTextIndex);
-                                }
-                                // If in front we have one space and before also we had space let's drop one space
-                                if (nodeText.getElements().size() > nodeTextIndex && nodeTextIndex > 0) {
-                                    if (nodeText.getElements().get(nodeTextIndex).isWhiteSpace()
-                                            && nodeText.getElements().get(nodeTextIndex - 1).isWhiteSpace()) {
-                                        // However we do not want to do that when we are about to adding or removing elements
-                                        if ((diffIndex + 1) == this.elements.size() || (elements.get(diffIndex + 1) instanceof Kept)) {
-                                            nodeText.getElements().remove(nodeTextIndex--);
-                                        }
-                                    }
-                                }
-                            }
-                            diffIndex++;
-                        }
-                    } else if ((removed.element instanceof CsmToken) && nodeTextEl instanceof TokenTextElement
-                            && ((CsmToken)removed.element).getTokenType() == ((TokenTextElement)nodeTextEl).getTokenKind()) {
-                        nodeText.removeElement(nodeTextIndex);
-                        diffIndex++;
-                    } else if (nodeTextEl instanceof TokenTextElement
-                            && nodeTextEl.isWhiteSpaceOrComment()) {
-                        nodeTextIndex++;
-                    } else if (removed.element instanceof CsmChild
-                            && ((CsmChild)removed.element).getChild() instanceof PrimitiveType) {
-                        if (isPrimitiveType(nodeTextEl)) {
-                            nodeText.removeElement(nodeTextIndex);
-                            diffIndex++;
-                        } else {
-                            throw new UnsupportedOperationException("removed " + removed.element + " vs " + nodeTextEl);
-                        }
-                    } else if (removed.element instanceof CsmToken && ((CsmToken)removed.element).isWhiteSpace()) {
-                        diffIndex++;
-                    } else if (nodeTextEl.isWhiteSpace()) {
-                        nodeTextIndex++;
-                    } else {
-                        throw new UnsupportedOperationException("removed " + removed.element + " vs " + nodeTextEl);
-                    }
-                } else if (diffEl instanceof Reshuffled) {
-
-                    // First, let's see how many tokens we need to attribute to the previous version of the of the CsmMix
-                    Reshuffled reshuffled = (Reshuffled)diffEl;
-                    CsmMix elementsFromPreviousOrder = reshuffled.previousOrder;
-                    CsmMix elementsFromNextOrder = reshuffled.element;
-
-                    // This contains indexes from elementsFromNextOrder to indexes from elementsFromPreviousOrder
-                    Map<Integer, Integer> correspondanceBetweenNextOrderAndPreviousOrder = new HashMap<>();
-                    for (int ni=0;ni<elementsFromNextOrder.getElements().size();ni++) {
-                        boolean found = false;
-                        CsmElement ne = elementsFromNextOrder.getElements().get(ni);
-                        for (int pi=0;pi<elementsFromPreviousOrder.getElements().size() && !found;pi++) {
-                            CsmElement pe = elementsFromPreviousOrder.getElements().get(pi);
-                            if (!correspondanceBetweenNextOrderAndPreviousOrder.values().contains(pi)
-                                    && matching(ne, pe)) {
-                                found = true;
-                                correspondanceBetweenNextOrderAndPreviousOrder.put(ni, pi);
-                            }
-                        }
-                    }
-
-                    // We now find out which Node Text elements corresponds to the elements in the original CSM
-                    final int startNodeTextIndex = nodeTextIndex;
-                    final Set<Integer> usedIndexes = new HashSet<>();
-                    List<Integer> nodeTextIndexOfPreviousElements = elementsFromPreviousOrder.getElements().stream()
-                            .map(it -> findIndexOfCorrespondingNodeTextElement(it, nodeText, startNodeTextIndex, usedIndexes, node))
-                            .collect(Collectors.toList());
-                    Map<Integer, Integer> nodeTextIndexToPreviousCSMIndex = new HashMap<>();
-                    for (int i=0;i<nodeTextIndexOfPreviousElements.size();i++) {
-                        int value = nodeTextIndexOfPreviousElements.get(i);
-                        if (value != -1) {
-                            nodeTextIndexToPreviousCSMIndex.put(value, i);
-                        }
-                    }
-                    int lastNodeTextIndex = nodeTextIndexOfPreviousElements.stream().max(Integer::compareTo).orElse(-1);
-
-                    // Elements to be added at the end
-                    List<CsmElement> elementsToBeAddedAtTheEnd = new LinkedList<>();
-                    Map<Integer, List<CsmElement>> elementsToAddBeforeGivenOriginalCSMElement = new HashMap<>();
-                    for (int ni=0;ni<elementsFromNextOrder.getElements().size();ni++) {
-                        // If it has a mapping, then it is kept
-                        if (!correspondanceBetweenNextOrderAndPreviousOrder.containsKey(ni)) {
-                            // Ok, it is something new. Where to put it? Let's see what is the first following
-                            // element that has a mapping
-                            int originalCsmIndex = -1;
-                            for (int nj=ni + 1;nj<elementsFromNextOrder.getElements().size() && originalCsmIndex==-1;nj++) {
-                                if (correspondanceBetweenNextOrderAndPreviousOrder.containsKey(nj)) {
-                                    originalCsmIndex = correspondanceBetweenNextOrderAndPreviousOrder.get(nj);
-                                    if (!elementsToAddBeforeGivenOriginalCSMElement.containsKey(originalCsmIndex)){
-                                        elementsToAddBeforeGivenOriginalCSMElement.put(originalCsmIndex, new LinkedList<>());
-                                    }
-                                    elementsToAddBeforeGivenOriginalCSMElement.get(originalCsmIndex).add(elementsFromNextOrder.getElements().get(ni));
-                                }
-                            }
-                            // it does not preceed anything, so it goes at the end
-                            if (originalCsmIndex == -1) {
-                                elementsToBeAddedAtTheEnd.add(elementsFromNextOrder.getElements().get(ni));
-                            }
-                        }
-                    }
-
-                    // We go over the original node text elements, in the order they appear in the NodeText.
-                    // Considering an original node text element (ONE)
-                    // * we verify if it corresponds to a CSM element. If it does not we just move on, otherwise
-                    //   we find the correspond OCE (Original CSM Element)
-                    // * we first add new elements that are marked to be added before OCE
-                    // * if OCE is marked to be present also in the "after" CSM we add a kept element,
-                    //   otherwise we add a removed element
-
-                    this.getElements().remove(diffIndex);
-                    int diffElIterator = diffIndex;
-                    if (lastNodeTextIndex != -1) {
-                        for (int ntIndex = startNodeTextIndex; ntIndex<=lastNodeTextIndex; ntIndex++) {
-
-                            if (nodeTextIndexToPreviousCSMIndex.containsKey(ntIndex)) {
-                                int indexOfOriginalCSMElement = nodeTextIndexToPreviousCSMIndex.get(ntIndex);
-                                if (elementsToAddBeforeGivenOriginalCSMElement.containsKey(indexOfOriginalCSMElement)) {
-                                    for (CsmElement elementToAdd : elementsToAddBeforeGivenOriginalCSMElement.get(indexOfOriginalCSMElement)) {
-                                        elements.add(diffElIterator++, new Added(elementToAdd));
-                                    }
-                                }
-
-                                CsmElement originalCSMElement = elementsFromPreviousOrder.getElements().get(indexOfOriginalCSMElement);
-                                boolean toBeKept = correspondanceBetweenNextOrderAndPreviousOrder.containsValue(indexOfOriginalCSMElement);
-                                if (toBeKept) {
-                                    elements.add(diffElIterator++, new Kept(originalCSMElement));
-                                } else {
-                                    elements.add(diffElIterator++, new Removed(originalCSMElement));
-                                }
-                            }
-                            // else we have a simple node text element, without associated csm element, just keep ignore it
-                        }
-                    }
-
-                    // Finally we look for the remaining new elements that were not yet added and
-                    // add all of them
-                    for (CsmElement elementToAdd : elementsToBeAddedAtTheEnd) {
-                        elements.add(diffElIterator++, new Added(elementToAdd));
-                    }
-                } else {
-                    throw new UnsupportedOperationException("" + diffEl + " vs " + nodeTextEl);
                 }
             }
-        } while (diffIndex < this.elements.size() || nodeTextIndex < nodeText.getElements().size());
+        } while (diffIndex < diffElements.size() || originalIndex < originalElements.size());
     }
 
-    private int findIndexOfCorrespondingNodeTextElement(CsmElement csmElement, NodeText nodeText, int startIndex, Set<Integer> usedIndexes, Node node) {
-        for (int i=startIndex;i<nodeText.getElements().size();i++){
-            if (!usedIndexes.contains(i)) {
-                TextElement textElement = nodeText.getTextElement(i);
-                if (csmElement instanceof CsmToken) {
-                    CsmToken csmToken = (CsmToken)csmElement;
-                    if (textElement instanceof TokenTextElement) {
-                        TokenTextElement tokenTextElement = (TokenTextElement)textElement;
-                        if (tokenTextElement.getTokenKind() == csmToken.getTokenType() && tokenTextElement.getText().equals(csmToken.getContent(node))) {
-                            usedIndexes.add(i);
-                            return i;
-                        }
-                    }
-                } else if (csmElement instanceof CsmChild) {
-                    CsmChild csmChild = (CsmChild)csmElement;
-                    if (textElement instanceof ChildTextElement) {
-                        ChildTextElement childTextElement = (ChildTextElement)textElement;
-                        if (childTextElement.getChild() == csmChild.getChild()) {
-                            usedIndexes.add(i);
-                            return i;
-                        }
-                    }
+    private boolean applyLeftOverOriginalElements() {
+        boolean isLeftOverElement = false;
+        if (diffIndex >= diffElements.size() && originalIndex < originalElements.size()) {
+            TextElement originalElement = originalElements.get(originalIndex);
+
+            if (originalElement.isWhiteSpaceOrComment()) {
+                originalIndex++;
+            } else {
+                throw new UnsupportedOperationException("NodeText: " + nodeText + ". Difference: "
+                        + this + " " + originalElement);
+            }
+
+            isLeftOverElement = true;
+        }
+        return isLeftOverElement;
+    }
+
+    private boolean applyLeftOverDiffElements() {
+        boolean isLeftOverElement = false;
+        if (diffIndex < diffElements.size() && originalIndex >= originalElements.size()) {
+            DifferenceElement diffElement = diffElements.get(diffIndex);
+            if (diffElement instanceof Kept) {
+                Kept kept = (Kept) diffElement;
+
+                if (kept.isWhiteSpaceOrComment() || kept.isIndent() || kept.isUnindent()) {
+                    diffIndex++;
                 } else {
-                    throw new UnsupportedOperationException();
+                    throw new IllegalStateException("Cannot keep element because we reached the end of nodetext: "
+                            + nodeText + ". Difference: " + this);
+                }
+            } else if (diffElement instanceof Added) {
+                Added addedElement = (Added) diffElement;
+
+                nodeText.addElement(originalIndex, addedElement.toTextElement());
+                originalIndex++;
+                diffIndex++;
+            } else {
+                throw new UnsupportedOperationException(diffElement.getClass().getSimpleName());
+            }
+
+            isLeftOverElement = true;
+        }
+
+        return isLeftOverElement;
+    }
+
+    private void extractReshuffledDiffElements(List<DifferenceElement> diffElements) {
+        for (int index = 0; index < diffElements.size(); index++) {
+            DifferenceElement diffElement = diffElements.get(index);
+            if (diffElement instanceof Reshuffled) {
+                Reshuffled reshuffled = (Reshuffled) diffElement;
+
+                // First, let's see how many tokens we need to attribute to the previous version of the of the CsmMix
+                CsmMix elementsFromPreviousOrder = reshuffled.getPreviousOrder();
+                CsmMix elementsFromNextOrder = reshuffled.getNextOrder();
+
+                // This contains indexes from elementsFromNextOrder to indexes from elementsFromPreviousOrder
+                Map<Integer, Integer> correspondanceBetweenNextOrderAndPreviousOrder = getCorrespondanceBetweenNextOrderAndPreviousOrder(elementsFromPreviousOrder, elementsFromNextOrder);
+
+                // We now find out which Node Text elements corresponds to the elements in the original CSM
+                List<Integer> nodeTextIndexOfPreviousElements = findIndexOfCorrespondingNodeTextElement(elementsFromPreviousOrder.getElements(), nodeText, originalIndex, node);
+
+                Map<Integer, Integer> nodeTextIndexToPreviousCSMIndex = new HashMap<>();
+                for (int i = 0; i < nodeTextIndexOfPreviousElements.size(); i++) {
+                    int value = nodeTextIndexOfPreviousElements.get(i);
+                    if (value != -1) {
+                        nodeTextIndexToPreviousCSMIndex.put(value, i);
+                    }
+                }
+                int lastNodeTextIndex = nodeTextIndexOfPreviousElements.stream().max(Integer::compareTo).orElse(-1);
+
+                // Elements to be added at the end
+                List<CsmElement> elementsToBeAddedAtTheEnd = new LinkedList<>();
+                List<CsmElement> nextOrderElements = elementsFromNextOrder.getElements();
+
+                Map<Integer, List<CsmElement>> elementsToAddBeforeGivenOriginalCSMElement = new HashMap<>();
+                for (int ni = 0; ni < nextOrderElements.size(); ni++) {
+                    // If it has a mapping, then it is kept
+                    if (!correspondanceBetweenNextOrderAndPreviousOrder.containsKey(ni)) {
+                        // Ok, it is something new. Where to put it? Let's see what is the first following
+                        // element that has a mapping
+                        int originalCsmIndex = -1;
+                        for (int nj = ni + 1; nj < nextOrderElements.size() && originalCsmIndex == -1; nj++) {
+                            if (correspondanceBetweenNextOrderAndPreviousOrder.containsKey(nj)) {
+                                originalCsmIndex = correspondanceBetweenNextOrderAndPreviousOrder.get(nj);
+                                if (!elementsToAddBeforeGivenOriginalCSMElement.containsKey(originalCsmIndex)) {
+                                    elementsToAddBeforeGivenOriginalCSMElement.put(originalCsmIndex, new LinkedList<>());
+                                }
+                                elementsToAddBeforeGivenOriginalCSMElement.get(originalCsmIndex).add(nextOrderElements.get(ni));
+                            }
+                        }
+                        // it does not preceed anything, so it goes at the end
+                        if (originalCsmIndex == -1) {
+                            elementsToBeAddedAtTheEnd.add(nextOrderElements.get(ni));
+                        }
+                    }
+                }
+
+                // We go over the original node text elements, in the order they appear in the NodeText.
+                // Considering an original node text element (ONE)
+                // * we verify if it corresponds to a CSM element. If it does not we just move on, otherwise
+                //   we find the correspond OCE (Original CSM Element)
+                // * we first add new elements that are marked to be added before OCE
+                // * if OCE is marked to be present also in the "after" CSM we add a kept element,
+                //   otherwise we add a removed element
+
+                // Remove the whole Reshuffled element
+                diffElements.remove(index);
+
+                int diffElIterator = index;
+                if (lastNodeTextIndex != -1) {
+                    for (int ntIndex = originalIndex; ntIndex <= lastNodeTextIndex; ntIndex++) {
+
+                        if (nodeTextIndexToPreviousCSMIndex.containsKey(ntIndex)) {
+                            int indexOfOriginalCSMElement = nodeTextIndexToPreviousCSMIndex.get(ntIndex);
+                            if (elementsToAddBeforeGivenOriginalCSMElement.containsKey(indexOfOriginalCSMElement)) {
+                                for (CsmElement elementToAdd : elementsToAddBeforeGivenOriginalCSMElement.get(indexOfOriginalCSMElement)) {
+                                    diffElements.add(diffElIterator++, new Added(elementToAdd));
+                                }
+                            }
+
+                            CsmElement originalCSMElement = elementsFromPreviousOrder.getElements().get(indexOfOriginalCSMElement);
+                            boolean toBeKept = correspondanceBetweenNextOrderAndPreviousOrder.containsValue(indexOfOriginalCSMElement);
+                            if (toBeKept) {
+                                diffElements.add(diffElIterator++, new Kept(originalCSMElement));
+                            } else {
+                                diffElements.add(diffElIterator++, new Removed(originalCSMElement));
+                            }
+                        }
+                        // else we have a simple node text element, without associated csm element, just keep ignore it
+                    }
+                }
+
+                // Finally we look for the remaining new elements that were not yet added and
+                // add all of them
+                for (CsmElement elementToAdd : elementsToBeAddedAtTheEnd) {
+                    diffElements.add(diffElIterator++, new Added(elementToAdd));
                 }
             }
         }
-        return -1;
+    }
+
+    /**
+     * Maps all Removed elements as keys to their corresponding RemovedGroup.
+     * A RemovedGroup contains all consecutive Removed elements.
+     * <br/>
+     * Example:
+     * <pre>
+     * Elements: Kept|Removed1|Removed2|Kept|Removed3|Added|Removed4
+     * Groups:        <----Group1---->       Group2         Group3
+     * Keys:          Removed1+Removed2      Removed3       Removed4
+     * </pre>
+     *
+     * @return Map with all Removed elements as keys to their corresponding RemovedGroup
+     */
+    private Map<Removed, RemovedGroup> combineRemovedElementsToRemovedGroups() {
+        Map<Integer, List<Removed>> removedElementsMap = groupConsecutiveRemovedElements();
+
+        List<RemovedGroup> removedGroups = new ArrayList<>();
+        for (Map.Entry<Integer, List<Removed>> entry : removedElementsMap.entrySet()) {
+            removedGroups.add(RemovedGroup.of(entry.getKey(), entry.getValue()));
+        }
+
+        Map<Removed, RemovedGroup> map = new HashMap<>();
+        for (RemovedGroup removedGroup : removedGroups){
+            for (Removed index : removedGroup) {
+                map.put(index, removedGroup);
+            }
+        }
+
+        return map;
+    }
+
+    private Map<Integer, List<Removed>> groupConsecutiveRemovedElements() {
+        Map<Integer, List<Removed>> removedElementsMap = new HashMap<>();
+
+        Integer firstElement = null;
+        for (int i = 0; i < diffElements.size(); i++) {
+            DifferenceElement diffElement = diffElements.get(i);
+            if (diffElement instanceof Removed) {
+                if (firstElement == null) {
+                    firstElement = i;
+                }
+
+                removedElementsMap.computeIfAbsent(firstElement, key -> new ArrayList<>())
+                        .add((Removed) diffElement);
+            } else {
+                firstElement = null;
+            }
+        }
+        return removedElementsMap;
+    }
+
+    private void applyRemovedDiffElement(RemovedGroup removedGroup, Removed removed, TextElement originalElement, boolean originalElementIsChild, boolean originalElementIsToken) {
+        if (removed.isChild() && originalElementIsChild) {
+            ChildTextElement originalElementChild = (ChildTextElement) originalElement;
+            if (originalElementChild.isComment()) {
+                // We expected to remove a proper node but we found a comment in between.
+                // If the comment is associated to the node we want to remove we remove it as well, otherwise we keep it
+                Comment comment = (Comment) originalElementChild.getChild();
+                if (!comment.isOrphan() && comment.getCommentedNode().isPresent() && comment.getCommentedNode().get().equals(removed.getChild())) {
+                    nodeText.removeElement(originalIndex);
+                } else {
+                    originalIndex++;
+                }
+            } else {
+                nodeText.removeElement(originalIndex);
+
+                if ((diffIndex + 1 >= diffElements.size() || !(diffElements.get(diffIndex + 1) instanceof Added))
+                        && !removedGroup.isACompleteLine()) {
+                    originalIndex = considerEnforcingIndentation(nodeText, originalIndex);
+                }
+                // If in front we have one space and before also we had space let's drop one space
+                if (originalElements.size() > originalIndex && originalIndex > 0) {
+                    if (originalElements.get(originalIndex).isWhiteSpace()
+                            && originalElements.get(originalIndex - 1).isWhiteSpace()) {
+                        // However we do not want to do that when we are about to adding or removing elements
+                        if ((diffIndex + 1) == diffElements.size() || (diffElements.get(diffIndex + 1) instanceof Kept)) {
+                            originalElements.remove(originalIndex--);
+                        }
+                    }
+                }
+
+                diffIndex++;
+            }
+        } else if (removed.isToken() && originalElementIsToken &&
+                (removed.getTokenType() == ((TokenTextElement) originalElement).getTokenKind()
+                        // handle EOLs separately as their token kind might not be equal. This is because the 'removed'
+                        // element always has the current operating system's EOL as type
+                        || (((TokenTextElement) originalElement).getToken().getCategory().isEndOfLine()
+                                && removed.isNewLine()))) {
+            nodeText.removeElement(originalIndex);
+            diffIndex++;
+        } else if (originalElementIsToken && originalElement.isWhiteSpaceOrComment()) {
+            originalIndex++;
+        } else if (removed.isPrimitiveType()) {
+            if (isPrimitiveType(originalElement)) {
+                nodeText.removeElement(originalIndex);
+                diffIndex++;
+            } else {
+                throw new UnsupportedOperationException("removed " + removed.getElement() + " vs " + originalElement);
+            }
+        } else if (removed.isWhiteSpace() || removed.getElement() instanceof CsmIndent || removed.getElement() instanceof CsmUnindent) {
+            diffIndex++;
+        } else if (originalElement.isWhiteSpace()) {
+            originalIndex++;
+        } else {
+            throw new UnsupportedOperationException("removed " + removed.getElement() + " vs " + originalElement);
+        }
+
+        cleanTheLineOfLeftOverSpace(removedGroup, removed);
+    }
+
+    /**
+     * Cleans the line of left over space if there is unnecessary indentation and the element will not be replaced
+     */
+    private void cleanTheLineOfLeftOverSpace(RemovedGroup removedGroup, Removed removed) {
+        if (originalIndex >= originalElements.size()) {
+            // if all elements were already processed there is nothing to do
+            return;
+        }
+
+        if (!removedGroup.isProcessed()
+                && removedGroup.getLastElement() == removed
+                && removedGroup.isACompleteLine()) {
+            Integer lastElementIndex = removedGroup.getLastElementIndex();
+            Optional<Integer> indentation = removedGroup.getIndentation();
+
+            if (indentation.isPresent() && !isReplaced(lastElementIndex)) {
+                for (int i = 0; i < indentation.get(); i++) {
+                    if (originalElements.get(originalIndex).isSpaceOrTab()) {
+                        // If the current element is a space, remove it
+                        nodeText.removeElement(originalIndex);
+                    } else if (originalIndex >= 1 && originalElements.get(originalIndex - 1).isSpaceOrTab()) {
+                        // If the current element is not a space itself we remove the space in front of it
+                        nodeText.removeElement(originalIndex - 1);
+                        originalIndex--;
+                    }
+                }
+            }
+
+            // Mark RemovedGroup as processed
+            removedGroup.processed();
+        }
+    }
+
+    private void applyKeptDiffElement(Kept kept, TextElement originalElement, boolean originalElementIsChild, boolean originalElementIsToken) {
+        if (originalElement.isComment()) {
+            originalIndex++;
+        } else if (kept.isChild() && originalElementIsChild) {
+            diffIndex++;
+            originalIndex++;
+        } else if (kept.isChild() && originalElementIsToken) {
+            if (originalElement.isWhiteSpaceOrComment()) {
+                originalIndex++;
+            } else {
+                if (kept.isPrimitiveType()) {
+                    originalIndex++;
+                    diffIndex++;
+                } else {
+                    throw new UnsupportedOperationException("kept " + kept.getElement() + " vs " + originalElement);
+                }
+            }
+        } else if (kept.isToken() && originalElementIsToken) {
+            TokenTextElement originalTextToken = (TokenTextElement) originalElement;
+
+            if (kept.getTokenType() == originalTextToken.getTokenKind()) {
+                originalIndex++;
+                diffIndex++;
+            } else if (kept.isNewLine() && originalTextToken.isSpaceOrTab()) {
+                originalIndex++;
+                diffIndex++;
+            } else if (kept.isWhiteSpaceOrComment()) {
+                diffIndex++;
+            } else if (originalTextToken.isWhiteSpaceOrComment()) {
+                originalIndex++;
+            } else {
+                throw new UnsupportedOperationException("Csm token " + kept.getElement() + " NodeText TOKEN " + originalTextToken);
+            }
+        } else if (kept.isWhiteSpace()) {
+            diffIndex++;
+        } else if (kept.isIndent()) {
+            diffIndex++;
+        } else if (kept.isUnindent()) {
+            // Nothing to do, beside considering indentation
+            // However we want to consider the case in which the indentation was not applied, like when we have
+            // just a left brace followed by space
+
+            diffIndex++;
+            if (!openBraceWasOnSameLine()) {
+                for (int i = 0; i < STANDARD_INDENTATION_SIZE && originalIndex >= 1 && nodeText.getTextElement(originalIndex - 1).isSpaceOrTab(); i++) {
+                    nodeText.removeElement(--originalIndex);
+                }
+            }
+        } else {
+            throw new UnsupportedOperationException("kept " + kept.getElement() + " vs " + originalElement);
+        }
+    }
+
+    private boolean openBraceWasOnSameLine() {
+        int index = originalIndex;
+        while (index >= 0 && !nodeText.getTextElement(index).isNewline()) {
+            if (nodeText.getTextElement(index).isToken(LBRACE)) {
+                return true;
+            }
+            index--;
+        }
+        return false;
+    }
+
+    private boolean wasSpaceBetweenBraces() {
+        return nodeText.getTextElement(originalIndex).isToken(RBRACE)
+                && doWeHaveLeftBraceFollowedBySpace(originalIndex - 1)
+                && (diffIndex < 2 || !diffElements.get(diffIndex - 2).isRemoved());
+    }
+
+    private boolean doWeHaveLeftBraceFollowedBySpace(int index) {
+        index = rewindSpace(index);
+        return nodeText.getElements().get(index).isToken(LBRACE);
+    }
+
+    private int rewindSpace(int index) {
+        if (index <= 0) {
+            return index;
+        }
+        if (nodeText.getElements().get(index).isWhiteSpace()) {
+            return rewindSpace(index - 1);
+        } else {
+            return index;
+        }
+    }
+
+    private boolean nextIsRightBrace(int index) {
+        List<TextElement> elements = originalElements.subList(index, originalElements.size());
+        for(TextElement element : elements) {
+            if (!element.isSpaceOrTab()) {
+                return element.isToken(RBRACE);
+            }
+        }
+        return false;
+    }
+
+    private void applyAddedDiffElement(Added added) {
+        if (added.isIndent()) {
+            for (int i=0;i<STANDARD_INDENTATION_SIZE;i++){
+                indentation.add(new TokenTextElement(GeneratedJavaParserConstants.SPACE));
+            }
+            addedIndentation = true;
+            diffIndex++;
+            return;
+        }
+        if (added.isUnindent()) {
+            for (int i = 0; i<STANDARD_INDENTATION_SIZE && !indentation.isEmpty(); i++){
+                indentation.remove(indentation.size() - 1);
+            }
+            addedIndentation = false;
+            diffIndex++;
+            return;
+        }
+
+        TextElement addedTextElement = added.toTextElement();
+        boolean used = false;
+        if (originalIndex > 0 && originalElements.get(originalIndex - 1).isNewline()) {
+            List<TextElement> elements = processIndentation(indentation, originalElements.subList(0, originalIndex - 1));
+            boolean nextIsRightBrace = nextIsRightBrace(originalIndex);
+            for (TextElement e : elements) {
+                if (!nextIsRightBrace
+                        && e instanceof TokenTextElement
+                        && originalElements.get(originalIndex).isToken(((TokenTextElement)e).getTokenKind())) {
+                    originalIndex++;
+                } else {
+                    nodeText.addElement(originalIndex++, e);
+                }
+            }
+        } else if (isAfterLBrace(nodeText, originalIndex) && !isAReplacement(diffIndex)) {
+            if (addedTextElement.isNewline()) {
+                used = true;
+            }
+            nodeText.addElement(originalIndex++, new TokenTextElement(TokenTypes.eolTokenKind()));
+            // This remove the space in "{ }" when adding a new line
+            while (originalIndex >= 2 && originalElements.get(originalIndex - 2).isSpaceOrTab()) {
+                originalElements.remove(originalIndex - 2);
+                originalIndex--;
+            }
+            for (TextElement e : processIndentation(indentation, originalElements.subList(0, originalIndex - 1))) {
+                nodeText.addElement(originalIndex++, e);
+            }
+            // Indentation is painful...
+            // Sometimes we want to force indentation: this is the case when indentation was expected but
+            // was actually not there. For example if we have "{ }" we would expect indentation but it is
+            // not there, so when adding new elements we force it. However if the indentation has been
+            // inserted by us in this transformation we do not want to insert it again
+            if (!addedIndentation) {
+                for (TextElement e : indentationBlock()) {
+                    nodeText.addElement(originalIndex++, e);
+                }
+            }
+        }
+
+        if (!used) {
+            // Handling trailing comments
+            if(nodeText.numberOfElements() > originalIndex + 1 &&
+                    nodeText.getTextElement(originalIndex).isComment()) {
+                // Need to get behind the comment:
+                originalIndex += 2;
+                nodeText.addElement(originalIndex, addedTextElement); // Defer originalIndex increment
+                // We want to adjust the indentation while considering the new element that we added
+                originalIndex = adjustIndentation(indentation, nodeText, originalIndex, false);
+                originalIndex++; // Now we can increment
+            } else {
+                nodeText.addElement(originalIndex, addedTextElement);
+                originalIndex++;
+            }
+        }
+
+        if (addedTextElement.isNewline()) {
+            boolean followedByUnindent = isFollowedByUnindent(diffElements, diffIndex);
+            boolean nextIsRightBrace = nextIsRightBrace(originalIndex);
+            boolean nextIsNewLine = nodeText.getTextElement(originalIndex).isNewline();
+            if ((!nextIsNewLine && !nextIsRightBrace) || followedByUnindent) {
+                originalIndex = adjustIndentation(indentation, nodeText, originalIndex, followedByUnindent);
+            }
+        }
+
+        diffIndex++;
+    }
+
+    private Map<Integer, Integer> getCorrespondanceBetweenNextOrderAndPreviousOrder(CsmMix elementsFromPreviousOrder, CsmMix elementsFromNextOrder) {
+        Map<Integer, Integer> correspondanceBetweenNextOrderAndPreviousOrder = new HashMap<>();
+
+        List<CsmElement> nextOrderElements = elementsFromNextOrder.getElements();
+        List<CsmElement> previousOrderElements = elementsFromPreviousOrder.getElements();
+        WrappingRangeIterator piNext = new WrappingRangeIterator(previousOrderElements.size());
+
+        for (int ni = 0; ni < nextOrderElements.size(); ni++) {
+            boolean found = false;
+            CsmElement ne = nextOrderElements.get(ni);
+
+            for (int counter = 0; counter < previousOrderElements.size() && !found; counter++) {
+                Integer pi = piNext.next();
+                CsmElement pe = previousOrderElements.get(pi);
+                if (!correspondanceBetweenNextOrderAndPreviousOrder.values().contains(pi)
+                        && DifferenceElementCalculator.matching(ne, pe)) {
+                    found = true;
+                    correspondanceBetweenNextOrderAndPreviousOrder.put(ni, pi);
+                }
+            }
+        }
+
+        return correspondanceBetweenNextOrderAndPreviousOrder;
+    }
+
+    private boolean isFollowedByUnindent(List<DifferenceElement> diffElements, int diffIndex) {
+        return (diffIndex + 1) < diffElements.size()
+                && diffElements.get(diffIndex + 1).isAdded()
+                && diffElements.get(diffIndex + 1).getElement() instanceof CsmUnindent;
+    }
+
+    private List<Integer> findIndexOfCorrespondingNodeTextElement(List<CsmElement> elements, NodeText nodeText, int startIndex, Node node) {
+        List<Integer> correspondingIndices = new ArrayList<>();
+        for (ListIterator<CsmElement> csmElementListIterator = elements.listIterator(); csmElementListIterator.hasNext(); ) {
+
+            int previousCsmElementIndex = csmElementListIterator.previousIndex();
+            CsmElement csmElement = csmElementListIterator.next();
+            int nextCsmElementIndex = csmElementListIterator.nextIndex();
+
+            Map<MatchClassification, Integer> potentialMatches = new EnumMap<>(MatchClassification.class);
+            for (int i = startIndex; i < nodeText.getElements().size(); i++){
+                if (!correspondingIndices.contains(i)) {
+                    TextElement textElement = nodeText.getTextElement(i);
+
+                    boolean isCorresponding = isCorrespondingElement(textElement, csmElement, node);
+
+                    if (isCorresponding) {
+                        boolean hasSamePreviousElement = false;
+                        if (i > 0 && previousCsmElementIndex > -1) {
+                            TextElement previousTextElement = nodeText.getTextElement(i - 1);
+
+                            hasSamePreviousElement = isCorrespondingElement(previousTextElement, elements.get(previousCsmElementIndex), node);
+                        }
+
+                        boolean hasSameNextElement = false;
+                        if (i < nodeText.getElements().size() - 1 && nextCsmElementIndex < elements.size()) {
+                            TextElement nextTextElement = nodeText.getTextElement(i + 1);
+
+                            hasSameNextElement = isCorrespondingElement(nextTextElement, elements.get(nextCsmElementIndex), node);
+                        }
+
+                        if (hasSamePreviousElement && hasSameNextElement) {
+                            potentialMatches.putIfAbsent(MatchClassification.ALL, i);
+                        } else if (hasSamePreviousElement) {
+                            potentialMatches.putIfAbsent(MatchClassification.PREVIOUS_AND_SAME, i);
+                        } else if (hasSameNextElement) {
+                            potentialMatches.putIfAbsent(MatchClassification.NEXT_AND_SAME, i);
+                        } else {
+                            potentialMatches.putIfAbsent(MatchClassification.SAME_ONLY, i);
+                        }
+                    } else if (isAlmostCorrespondingElement(textElement, csmElement, node)) {
+                        potentialMatches.putIfAbsent(MatchClassification.ALMOST, i);
+                    }
+                }
+            }
+
+            // Prioritize the matches from best to worst
+            Optional<MatchClassification> bestMatchKey = potentialMatches.keySet().stream()
+                    .min(Comparator.comparing(MatchClassification::getPriority));
+
+            if (bestMatchKey.isPresent()) {
+                correspondingIndices.add(potentialMatches.get(bestMatchKey.get()));
+            } else {
+                correspondingIndices.add(-1);
+            }
+        }
+
+        return correspondingIndices;
+    }
+
+    private enum MatchClassification {
+        ALL(1), PREVIOUS_AND_SAME(2), NEXT_AND_SAME(3), SAME_ONLY(4), ALMOST(5);
+
+        private final int priority;
+        MatchClassification(int priority) {
+            this.priority = priority;
+        }
+
+        int getPriority() {
+            return priority;
+        }
+    }
+
+    private boolean isCorrespondingElement(TextElement textElement, CsmElement csmElement, Node node) {
+        if (csmElement instanceof CsmToken) {
+            CsmToken csmToken = (CsmToken)csmElement;
+            if (textElement instanceof TokenTextElement) {
+                TokenTextElement tokenTextElement = (TokenTextElement)textElement;
+                return tokenTextElement.getTokenKind() == csmToken.getTokenType() && tokenTextElement.getText().equals(csmToken.getContent(node));
+            }
+        } else if (csmElement instanceof CsmChild) {
+            CsmChild csmChild = (CsmChild)csmElement;
+            if (textElement instanceof ChildTextElement) {
+                ChildTextElement childTextElement = (ChildTextElement)textElement;
+                return childTextElement.getChild() == csmChild.getChild();
+            }
+        } else {
+            throw new UnsupportedOperationException();
+        }
+
+        return false;
+    }
+
+    private boolean isAlmostCorrespondingElement(TextElement textElement, CsmElement csmElement, Node node) {
+        if (isCorrespondingElement(textElement, csmElement, node)) {
+            return false;
+        }
+        return textElement.isWhiteSpace() && csmElement instanceof CsmToken && ((CsmToken)csmElement).isWhiteSpace();
     }
 
     private int adjustIndentation(List<TokenTextElement> indentation, NodeText nodeText, int nodeTextIndex, boolean followedByUnindent) {
@@ -833,17 +756,24 @@
             indentationAdj = indentationAdj.subList(0, Math.max(0, indentationAdj.size() - STANDARD_INDENTATION_SIZE));
         }
         for (TextElement e : indentationAdj) {
-            if ((nodeTextIndex<nodeText.getElements().size()) && nodeText.getElements().get(nodeTextIndex).isSpaceOrTab()) {
+            if ((nodeTextIndex< nodeText.getElements().size()) && nodeText.getElements().get(nodeTextIndex).isSpaceOrTab()) {
                 nodeTextIndex++;
             } else {
                 nodeText.getElements().add(nodeTextIndex++, e);
             }
         }
+        if (nodeTextIndex < 0) {
+            throw new IllegalStateException();
+        }
         return nodeTextIndex;
     }
 
     private boolean isAReplacement(int diffIndex) {
-        return (diffIndex > 0) && getElements().get(diffIndex) instanceof Added && getElements().get(diffIndex - 1) instanceof Removed;
+        return (diffIndex > 0) && diffElements.get(diffIndex) instanceof Added && diffElements.get(diffIndex - 1) instanceof Removed;
+    }
+
+    private boolean isReplaced(int diffIndex) {
+        return (diffIndex < diffElements.size() - 1) && diffElements.get(diffIndex + 1) instanceof Added && diffElements.get(diffIndex) instanceof Removed;
     }
 
     private boolean isPrimitiveType(TextElement textElement) {
@@ -861,25 +791,8 @@
             return false;
         }
     }
-
-    private long cost() {
-        return elements.stream().filter(e -> !(e instanceof Kept)).count();
-    }
-
     @Override
     public String toString() {
-        return "Difference{" + elements + '}';
-    }
-
-    public List<DifferenceElement> getElements() {
-        return elements;
-    }
-
-    /**
-     * Remove from the difference all the elements related to indentation.
-     * This is mainly intended for test purposes.
-     */
-    void removeIndentationElements() {
-        elements.removeIf(el -> el.getElement() instanceof CsmIndent || el.getElement() instanceof CsmUnindent);
+        return "Difference{" + diffElements + '}';
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElement.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElement.java
new file mode 100644
index 0000000..ebf3433
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElement.java
@@ -0,0 +1,26 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
+
+public interface DifferenceElement {
+    static DifferenceElement added(CsmElement element) {
+        return new Added(element);
+    }
+
+    static DifferenceElement removed(CsmElement element) {
+        return new Removed(element);
+    }
+
+    static DifferenceElement kept(CsmElement element) {
+        return new Kept(element);
+    }
+
+    /**
+     * Return the CsmElement considered in this DifferenceElement.
+     */
+    CsmElement getElement();
+
+    boolean isAdded();
+
+    boolean isRemoved();
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculator.java
new file mode 100644
index 0000000..7855422
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/DifferenceElementCalculator.java
@@ -0,0 +1,241 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.type.Type;
+import com.github.javaparser.printer.concretesyntaxmodel.*;
+import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild;
+
+import java.util.*;
+
+class DifferenceElementCalculator {
+    static boolean matching(CsmElement a, CsmElement b) {
+        if (a instanceof CsmChild) {
+            if (b instanceof CsmChild) {
+                CsmChild childA = (CsmChild) a;
+                CsmChild childB = (CsmChild) b;
+                return childA.getChild().equals(childB.getChild());
+            } else if (b instanceof CsmToken) {
+                return false;
+            } else if (b instanceof CsmIndent) {
+                return false;
+            } else if (b instanceof CsmUnindent) {
+                return false;
+            } else {
+                throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
+            }
+        } else if (a instanceof CsmToken) {
+            if (b instanceof CsmToken) {
+                CsmToken childA = (CsmToken)a;
+                CsmToken childB = (CsmToken)b;
+                return childA.getTokenType() == childB.getTokenType();
+            } else if (b instanceof CsmChild) {
+                return false;
+            } else if (b instanceof CsmIndent) {
+                return false;
+            } else if (b instanceof CsmUnindent) {
+                return false;
+            } else {
+                throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
+            }
+        } else if (a instanceof CsmIndent) {
+            return b instanceof CsmIndent;
+        } else if (a instanceof CsmUnindent) {
+            return b instanceof CsmUnindent;
+        }
+        throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
+    }
+
+    private static boolean replacement(CsmElement a, CsmElement b) {
+        if (a instanceof CsmIndent || b instanceof CsmIndent || a instanceof CsmUnindent || b instanceof CsmUnindent) {
+            return false;
+        }
+        if (a instanceof CsmChild) {
+            if (b instanceof CsmChild) {
+                CsmChild childA = (CsmChild) a;
+                CsmChild childB = (CsmChild) b;
+                return childA.getChild().getClass().equals(childB.getChild().getClass());
+            } else if (b instanceof CsmToken) {
+                return false;
+            } else {
+                throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
+            }
+        } else if (a instanceof CsmToken) {
+            if (b instanceof CsmToken) {
+                CsmToken childA = (CsmToken)a;
+                CsmToken childB = (CsmToken)b;
+                return childA.getTokenType() == childB.getTokenType();
+            } else if (b instanceof CsmChild) {
+                return false;
+            }
+        }
+        throw new UnsupportedOperationException(a.getClass().getSimpleName()+ " "+b.getClass().getSimpleName());
+    }
+
+    /**
+     * Find the positions of all the given children.
+     */
+    private static Map<Node, Integer> findChildrenPositions(LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel) {
+        Map<Node, Integer> positions = new HashMap<>();
+        for (int i=0;i<calculatedSyntaxModel.elements.size();i++) {
+            CsmElement element = calculatedSyntaxModel.elements.get(i);
+            if (element instanceof CsmChild) {
+                positions.put(((CsmChild)element).getChild(), i);
+            }
+        }
+        return positions;
+    }
+
+    /**
+     * Calculate the Difference between two CalculatedSyntaxModel elements, determining which elements were kept,
+     * which were added and which were removed.
+     */
+    static List<DifferenceElement> calculate(LexicalDifferenceCalculator.CalculatedSyntaxModel original, LexicalDifferenceCalculator.CalculatedSyntaxModel after) {
+        // For performance reasons we use the positions of matching children
+        // to guide the calculation of the difference
+        //
+        // Suppose we have:
+        //   qwerty[A]uiop
+        //   qwer[A]uiop
+        //
+        // with [A] being a child and lowercase letters being tokens
+        //
+        // We would calculate the Difference between "qwerty" and "qwer" then we know the A is kept, and then we
+        // would calculate the difference between "uiop" and "uiop"
+
+        Map<Node, Integer> childrenInOriginal = findChildrenPositions(original);
+        Map<Node, Integer> childrenInAfter = findChildrenPositions(after);
+
+        List<Node> commonChildren = new LinkedList<>(childrenInOriginal.keySet());
+        commonChildren.retainAll(childrenInAfter.keySet());
+        commonChildren.sort(Comparator.comparingInt(childrenInOriginal::get));
+
+        List<DifferenceElement> elements = new LinkedList<>();
+
+        int originalIndex = 0;
+        int afterIndex = 0;
+        int commonChildrenIndex = 0;
+        while (commonChildrenIndex < commonChildren.size()) {
+            Node child = commonChildren.get(commonChildrenIndex++);
+            int posOfNextChildInOriginal = childrenInOriginal.get(child);
+            int posOfNextChildInAfter    = childrenInAfter.get(child);
+            if (originalIndex < posOfNextChildInOriginal || afterIndex < posOfNextChildInAfter) {
+                elements.addAll(calculateImpl(original.sub(originalIndex, posOfNextChildInOriginal), after.sub(afterIndex, posOfNextChildInAfter)));
+            }
+            elements.add(new Kept(new CsmChild(child)));
+            originalIndex = posOfNextChildInOriginal + 1;
+            afterIndex = posOfNextChildInAfter + 1;
+        }
+
+        if (originalIndex < original.elements.size() || afterIndex < after.elements.size()) {
+            elements.addAll(calculateImpl(original.sub(originalIndex, original.elements.size()), after.sub(afterIndex, after.elements.size())));
+        }
+        return elements;
+    }
+
+    private static void considerRemoval(NodeText nodeTextForChild, List<DifferenceElement> elements) {
+        for (TextElement el : nodeTextForChild.getElements()) {
+            if (el instanceof ChildTextElement) {
+                ChildTextElement cte = (ChildTextElement) el;
+                considerRemoval(LexicalPreservingPrinter.getOrCreateNodeText(cte.getChild()), elements);
+            } else if (el instanceof TokenTextElement) {
+                TokenTextElement tte = (TokenTextElement) el;
+                elements.add(new Removed(new CsmToken(tte.getTokenKind(), tte.getText())));
+            } else {
+                throw new UnsupportedOperationException(el.toString());
+            }
+        }
+    }
+
+    private static int considerRemoval(CsmElement removedElement, int originalIndex, List<DifferenceElement> elements) {
+        boolean dealtWith = false;
+        if (removedElement instanceof CsmChild) {
+            CsmChild removedChild = (CsmChild) removedElement;
+            if (removedChild.getChild() instanceof Type && removedChild.getChild().getParentNode().isPresent() &&
+                    removedChild.getChild().getParentNode().get() instanceof VariableDeclarator) {
+                NodeText nodeTextForChild = LexicalPreservingPrinter.getOrCreateNodeText(removedChild.getChild());
+                considerRemoval(nodeTextForChild, elements);
+                originalIndex++;
+                dealtWith = true;
+            }
+        }
+        if (!dealtWith) {
+            elements.add(new Removed(removedElement));
+            originalIndex++;
+        }
+        return originalIndex;
+    }
+
+    private static List<DifferenceElement> calculateImpl(LexicalDifferenceCalculator.CalculatedSyntaxModel original,
+                                                         LexicalDifferenceCalculator.CalculatedSyntaxModel after) {
+        List<DifferenceElement> elements = new LinkedList<>();
+
+        int originalIndex = 0;
+        int afterIndex = 0;
+
+        // We move through the two CalculatedSyntaxModel, moving both forward when we have a match
+        // and moving just one side forward when we have an element kept or removed
+
+        do {
+            if (originalIndex < original.elements.size() && afterIndex >= after.elements.size()) {
+                CsmElement removedElement = original.elements.get(originalIndex);
+                originalIndex = considerRemoval(removedElement, originalIndex, elements);
+            } else if (originalIndex >= original.elements.size() && afterIndex < after.elements.size()) {
+                elements.add(new Added(after.elements.get(afterIndex)));
+                afterIndex++;
+            } else {
+                CsmElement nextOriginal = original.elements.get(originalIndex);
+                CsmElement nextAfter = after.elements.get(afterIndex);
+
+                if ((nextOriginal instanceof CsmMix) && (nextAfter instanceof CsmMix)) {
+                    if (((CsmMix) nextAfter).getElements().equals(((CsmMix) nextOriginal).getElements())) {
+                        // No reason to deal with a reshuffled, we are just going to keep everything as it is
+                        ((CsmMix) nextAfter).getElements().forEach(el -> elements.add(new Kept(el)));
+                    } else {
+                        elements.add(new Reshuffled((CsmMix)nextOriginal, (CsmMix)nextAfter));
+                    }
+                    originalIndex++;
+                    afterIndex++;
+                } else if (matching(nextOriginal, nextAfter)) {
+                    elements.add(new Kept(nextOriginal));
+                    originalIndex++;
+                    afterIndex++;
+                } else if (replacement(nextOriginal, nextAfter)) {
+                    originalIndex = considerRemoval(nextOriginal, originalIndex, elements);
+                    elements.add(new Added(nextAfter));
+                    afterIndex++;
+                } else {
+                    // We can try to remove the element or add it and look which one leads to the lower difference
+                    List<DifferenceElement> addingElements = calculate(original.from(originalIndex), after.from(afterIndex + 1));
+                    List<DifferenceElement> removingElements = null;
+                    if (cost(addingElements) > 0) {
+                        removingElements = calculate(original.from(originalIndex + 1), after.from(afterIndex));
+                    }
+
+                    if (removingElements == null || cost(removingElements) > cost(addingElements)) {
+                        elements.add(new Added(nextAfter));
+                        afterIndex++;
+                    } else {
+                        elements.add(new Removed(nextOriginal));
+                        originalIndex++;
+                    }
+                }
+            }
+        } while (originalIndex < original.elements.size() || afterIndex < after.elements.size());
+
+        return elements;
+    }
+
+    private static long cost(List<DifferenceElement> elements) {
+        return elements.stream().filter(e -> !(e instanceof Kept)).count();
+    }
+
+
+    /**
+     * Remove from the difference all the elements related to indentation.
+     * This is mainly intended for test purposes.
+     */
+    static void removeIndentationElements(List<DifferenceElement> elements) {
+        elements.removeIf(el -> el.getElement() instanceof CsmIndent || el.getElement() instanceof CsmUnindent);
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Kept.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Kept.java
new file mode 100644
index 0000000..6192bbe
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Kept.java
@@ -0,0 +1,104 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.TokenTypes;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmIndent;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmUnindent;
+
+public class Kept implements DifferenceElement {
+    private final CsmElement element;
+
+    Kept(CsmElement element) {
+        this.element = element;
+    }
+
+    @Override
+    public String toString() {
+        return "Kept{" + element + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Kept kept = (Kept) o;
+
+        return element.equals(kept.element);
+    }
+
+    @Override
+    public int hashCode() {
+        return element.hashCode();
+    }
+
+    @Override
+    public CsmElement getElement() {
+        return element;
+    }
+
+    public int getTokenType() {
+        if (isToken()) {
+            CsmToken csmToken = (CsmToken) element;
+            return csmToken.getTokenType();
+        }
+
+        throw new IllegalStateException("Kept is not a " + CsmToken.class.getSimpleName());
+    }
+
+    @Override
+    public boolean isAdded() {
+        return false;
+    }
+
+    public boolean isIndent() { return element instanceof CsmIndent; }
+
+    public boolean isUnindent() { return element instanceof CsmUnindent; }
+
+    public boolean isToken() { return element instanceof CsmToken; }
+
+    public boolean isChild() { return element instanceof LexicalDifferenceCalculator.CsmChild; }
+
+    public boolean isPrimitiveType() {
+        if (isChild()) {
+            LexicalDifferenceCalculator.CsmChild csmChild = (LexicalDifferenceCalculator.CsmChild) element;
+            return csmChild.getChild() instanceof PrimitiveType;
+        }
+
+        return false;
+    }
+
+    public boolean isWhiteSpace() {
+        if(isToken()) {
+            CsmToken csmToken = (CsmToken) element;
+            return csmToken.isWhiteSpace();
+        }
+
+        return false;
+    }
+
+    public boolean isWhiteSpaceOrComment() {
+        if (isToken()) {
+            CsmToken csmToken = (CsmToken) element;
+            return TokenTypes.isWhitespaceOrComment(csmToken.getTokenType());
+        }
+
+        return false;
+    }
+
+    public boolean isNewLine() {
+        if(isToken()) {
+            CsmToken csmToken = (CsmToken) element;
+            return csmToken.isNewLine();
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isRemoved() {
+        return false;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java
index 9263dfd..cd0f102 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java
@@ -86,39 +86,40 @@
         }
     }
 
-    Difference calculateListRemovalDifference(ObservableProperty observableProperty, NodeList nodeList, int index) {
+    List<DifferenceElement> calculateListRemovalDifference(ObservableProperty observableProperty, NodeList nodeList, int index) {
         Node container = nodeList.getParentNodeForChildren();
         CsmElement element = ConcreteSyntaxModel.forClass(container.getClass());
         CalculatedSyntaxModel original = calculatedSyntaxModelForNode(element, container);
         CalculatedSyntaxModel after = calculatedSyntaxModelAfterListRemoval(element, observableProperty, nodeList, index);
-        return Difference.calculate(original, after);
+        return DifferenceElementCalculator.calculate(original, after);
     }
 
-    Difference calculateListAdditionDifference(ObservableProperty observableProperty, NodeList nodeList, int index, Node nodeAdded) {
+    List<DifferenceElement> calculateListAdditionDifference(ObservableProperty observableProperty, NodeList nodeList, int index, Node nodeAdded) {
         Node container = nodeList.getParentNodeForChildren();
         CsmElement element = ConcreteSyntaxModel.forClass(container.getClass());
         CalculatedSyntaxModel original = calculatedSyntaxModelForNode(element, container);
         CalculatedSyntaxModel after = calculatedSyntaxModelAfterListAddition(element, observableProperty, nodeList, index, nodeAdded);
-        return Difference.calculate(original, after);
+        return DifferenceElementCalculator.calculate(original, after);
     }
 
-    Difference calculateListReplacementDifference(ObservableProperty observableProperty, NodeList nodeList, int index, Node newValue) {
+    List<DifferenceElement> calculateListReplacementDifference(ObservableProperty observableProperty, NodeList nodeList, int index, Node newValue) {
         Node container = nodeList.getParentNodeForChildren();
         CsmElement element = ConcreteSyntaxModel.forClass(container.getClass());
         CalculatedSyntaxModel original = calculatedSyntaxModelForNode(element, container);
         CalculatedSyntaxModel after = calculatedSyntaxModelAfterListReplacement(element, observableProperty, nodeList, index, newValue);
-        return Difference.calculate(original, after);
+        return DifferenceElementCalculator.calculate(original, after);
     }
 
-    public void calculatePropertyChange(NodeText nodeText, Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+    void calculatePropertyChange(NodeText nodeText, Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
         if (nodeText == null) {
             throw new NullPointerException();
         }
         CsmElement element = ConcreteSyntaxModel.forClass(observedNode.getClass());
         CalculatedSyntaxModel original = calculatedSyntaxModelForNode(element, observedNode);
         CalculatedSyntaxModel after = calculatedSyntaxModelAfterPropertyChange(element, observedNode, property, oldValue, newValue);
-        Difference difference = Difference.calculate(original, after);
-        difference.apply(nodeText, observedNode);
+        List<DifferenceElement> differenceElements = DifferenceElementCalculator.calculate(original, after);
+        Difference difference = new Difference(differenceElements, nodeText, observedNode);
+        difference.apply();
     }
 
     // Visible for testing
@@ -234,7 +235,7 @@
             if (value instanceof Printable) {
                 text = ((Printable) value).asString();
             }
-            elements.add(new CsmToken(csmAttribute.getTokenType(node, value.toString()), text));
+            elements.add(new CsmToken(csmAttribute.getTokenType(node, value.toString(), text), text));
         } else if ((csm instanceof CsmString) && (node instanceof StringLiteralExpr)) {
             elements.add(new CsmToken(GeneratedJavaParserConstants.STRING_LITERAL,
                     "\"" + ((StringLiteralExpr) node).getValue() + "\""));
@@ -243,13 +244,15 @@
             List<CsmElement> mixElements = new LinkedList<>();
             csmMix.getElements().forEach(e -> calculatedSyntaxModelForNode(e, node, mixElements, change));
             elements.add(new CsmMix(mixElements));
+        } else if (csm instanceof CsmChild) {
+            elements.add(csm);
         } else {
             throw new UnsupportedOperationException(csm.getClass().getSimpleName()+ " " + csm);
         }
     }
 
-    private int toToken(Modifier modifier) {
-        switch (modifier) {
+    public static int toToken(Modifier modifier) {
+        switch (modifier.getKeyword()) {
             case PUBLIC:
                 return GeneratedJavaParserConstants.PUBLIC;
             case PRIVATE:
@@ -263,7 +266,7 @@
             case ABSTRACT:
                 return GeneratedJavaParserConstants.ABSTRACT;
             default:
-                throw new UnsupportedOperationException(modifier.name());
+                throw new UnsupportedOperationException(modifier.getKeyword().name());
         }
     }
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinter.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinter.java
index ef647fb..23be38d 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinter.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinter.java
@@ -23,11 +23,14 @@
 
 import com.github.javaparser.*;
 import com.github.javaparser.ast.DataKey;
+import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.body.VariableDeclarator;
+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.nodeTypes.NodeWithVariables;
 import com.github.javaparser.ast.observer.AstObserver;
 import com.github.javaparser.ast.observer.ObservableProperty;
@@ -35,9 +38,7 @@
 import com.github.javaparser.ast.type.PrimitiveType;
 import com.github.javaparser.ast.visitor.TreeVisitor;
 import com.github.javaparser.printer.ConcreteSyntaxModel;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmMix;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+import com.github.javaparser.printer.concretesyntaxmodel.*;
 import com.github.javaparser.utils.Pair;
 import com.github.javaparser.utils.Utils;
 
@@ -63,33 +64,21 @@
  */
 public class LexicalPreservingPrinter {
 
+    private static AstObserver observer;
+
     /**
      * The nodetext for a node is stored in the node's data field. This is the key to set and retrieve it.
      */
     public static final DataKey<NodeText> NODE_TEXT_DATA = new DataKey<NodeText>() {
     };
 
+    private static final LexicalDifferenceCalculator LEXICAL_DIFFERENCE_CALCULATOR = new LexicalDifferenceCalculator();
+
     //
     // Factory methods
     //
 
     /**
-     * Parse the code and setup the LexicalPreservingPrinter.
-     *
-     * @deprecated use setup(Node) and the static methods on this class.
-     */
-    public static <N extends Node> Pair<ParseResult<N>, LexicalPreservingPrinter> setup(ParseStart<N> parseStart,
-                                                                                        Provider provider) {
-        ParseResult<N> parseResult = new JavaParser().parse(parseStart, provider);
-        if (!parseResult.isSuccessful()) {
-            throw new RuntimeException("Parsing failed, unable to setup the lexical preservation printer: "
-                    + parseResult.getProblems());
-        }
-        LexicalPreservingPrinter lexicalPreservingPrinter = new LexicalPreservingPrinter(parseResult.getResult().get());
-        return new Pair<>(parseResult, lexicalPreservingPrinter);
-    }
-
-    /**
      * Prepares the node so it can be used in the print methods.
      * The correct order is:
      * <ol>
@@ -104,13 +93,16 @@
     public static <N extends Node> N setup(N node) {
         assertNotNull(node);
 
+        if(observer == null) {
+            observer = createObserver();
+        }
+
         node.getTokenRange().ifPresent(r -> {
             storeInitialText(node);
-
             // Setup observer
-            AstObserver observer = createObserver();
-
-            node.registerForSubtree(observer);
+            if(!node.isRegistered(observer)) {
+                node.registerForSubtree(observer);
+            }
         });
         return node;
     }
@@ -119,94 +111,177 @@
     // Constructor and setup
     //
 
-    /**
-     * @deprecated use setup(Node) to prepare a node for lexical preservation,
-     * then use the static methods on this class to print it.
-     */
-    @Deprecated
-    public LexicalPreservingPrinter(Node node) {
-        setup(node);
+    private static AstObserver createObserver() {
+        return new LexicalPreservingPrinter.Observer();
     }
 
-    private static AstObserver createObserver() {
-        return new PropagatingAstObserver() {
-            @Override
-            public void concretePropertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                // Not really a change, ignoring
-                if ((oldValue != null && oldValue.equals(newValue)) || (oldValue == null && newValue == null)) {
-                    return;
+    private static class Observer extends PropagatingAstObserver {
+        @Override
+        public void concretePropertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
+            // Not really a change, ignoring
+            if ((oldValue != null && oldValue.equals(newValue)) || (oldValue == null && newValue == null)) {
+                return;
+            }
+            if (property == ObservableProperty.RANGE || property == ObservableProperty.COMMENTED_NODE) {
+                return;
+            }
+            if (property == ObservableProperty.COMMENT) {
+                if (!observedNode.getParentNode().isPresent()) {
+                    throw new IllegalStateException();
                 }
-                if (property == ObservableProperty.RANGE || property == ObservableProperty.COMMENTED_NODE) {
-                    return;
-                }
-                if (property == ObservableProperty.COMMENT) {
-                    if (!observedNode.getParentNode().isPresent()) {
-                        throw new IllegalStateException();
-                    }
-                    NodeText nodeText = getOrCreateNodeText(observedNode.getParentNode().get());
-                    if (oldValue == null) {
-                        // Find the position of the comment node and put in front of it the comment and a newline
-                        int index = nodeText.findChild(observedNode);
-                        nodeText.addChild(index, (Comment) newValue);
-                        nodeText.addToken(index + 1, eolTokenKind(), Utils.EOL);
-                    } else if (newValue == null) {
-                        if (oldValue instanceof JavadocComment) {
-                            JavadocComment javadocComment = (JavadocComment) oldValue;
-                            List<TokenTextElement> matchingTokens = nodeText.getElements().stream().filter(e -> e.isToken(JAVADOC_COMMENT)
-                                    && ((TokenTextElement) e).getText().equals("/**" + javadocComment.getContent() + "*/")).map(e -> (TokenTextElement) e).collect(Collectors.toList());
-                            if (matchingTokens.size() != 1) {
-                                throw new IllegalStateException();
-                            }
-                            int index = nodeText.findElement(matchingTokens.get(0));
+                
+                NodeText nodeText = getOrCreateNodeText(observedNode.getParentNode().get());
+                
+                if (oldValue == null) {
+                    // Find the position of the comment node and put in front of it the comment and a newline
+                    int index = nodeText.findChild(observedNode);
+                    nodeText.addChild(index, (Comment) newValue);
+                    nodeText.addToken(index + 1, eolTokenKind(), Utils.EOL);
+                } else if (newValue == null) {
+                    if (oldValue instanceof Comment) {
+                        if (((Comment) oldValue).isOrphan()){
+                            nodeText = getOrCreateNodeText(observedNode);
+                        }
+                        int index = getIndexOfComment ((Comment) oldValue, nodeText);
+                        nodeText.removeElement(index);
+                        if (nodeText.getElements().get(index).isNewline()) {
                             nodeText.removeElement(index);
-                            if (nodeText.getElements().get(index).isNewline()) {
-                                nodeText.removeElement(index);
-                            }
-                        } else {
-                            throw new UnsupportedOperationException();
                         }
                     } else {
-                        if (oldValue instanceof JavadocComment) {
-                            JavadocComment oldJavadocComment = (JavadocComment) oldValue;
-                            List<TokenTextElement> matchingTokens = nodeText.getElements().stream().filter(e -> e.isToken(JAVADOC_COMMENT)
-                                    && ((TokenTextElement) e).getText().equals("/**" + oldJavadocComment.getContent() + "*/")).map(e -> (TokenTextElement) e).collect(Collectors.toList());
-                            if (matchingTokens.size() != 1) {
-                                throw new IllegalStateException();
-                            }
-                            JavadocComment newJavadocComment = (JavadocComment) newValue;
-                            nodeText.replace(matchingTokens.get(0), new TokenTextElement(JAVADOC_COMMENT, "/**" + newJavadocComment.getContent() + "*/"));
-                        } else {
-                            throw new UnsupportedOperationException();
+                        throw new UnsupportedOperationException();
+                    }
+                } else {
+                    if (oldValue instanceof JavadocComment) {
+                        List<TokenTextElement> matchingTokens = findTokenTextElementForComment((JavadocComment) oldValue, nodeText);
+
+                        if (matchingTokens.size() != 1) {
+                            throw new IllegalStateException("The matching comment to be replaced could not be found");
                         }
+                        
+                        JavadocComment newJavadocComment = (JavadocComment) newValue;
+                        TokenTextElement matchingElement = matchingTokens.get(0);
+                        nodeText.replace(matchingElement.and(matchingElement.matchByRange()), new TokenTextElement(JAVADOC_COMMENT, "/**" + newJavadocComment.getContent() + "*/"));
+                    } else {
+                        throw new UnsupportedOperationException();
                     }
                 }
-                NodeText nodeText = getOrCreateNodeText(observedNode);
+            }
+            NodeText nodeText = getOrCreateNodeText(observedNode);
 
-                if (nodeText == null) {
-                    throw new NullPointerException(observedNode.getClass().getSimpleName());
-                }
-
-                new LexicalDifferenceCalculator().calculatePropertyChange(nodeText, observedNode, property, oldValue, newValue);
+            if (nodeText == null) {
+                throw new NullPointerException(observedNode.getClass().getSimpleName());
             }
 
-            @Override
-            public void concreteListChange(NodeList changedList, ListChangeType type, int index, Node nodeAddedOrRemoved) {
-                NodeText nodeText = getOrCreateNodeText(changedList.getParentNodeForChildren());
-                if (type == ListChangeType.REMOVAL) {
-                    new LexicalDifferenceCalculator().calculateListRemovalDifference(findNodeListName(changedList), changedList, index).apply(nodeText, changedList.getParentNodeForChildren());
-                } else if (type == ListChangeType.ADDITION) {
-                    new LexicalDifferenceCalculator().calculateListAdditionDifference(findNodeListName(changedList), changedList, index, nodeAddedOrRemoved).apply(nodeText, changedList.getParentNodeForChildren());
-                } else {
-                    throw new UnsupportedOperationException();
-                }
+            LEXICAL_DIFFERENCE_CALCULATOR.calculatePropertyChange(nodeText, observedNode, property, oldValue, newValue);
+        }
+        
+        private int getIndexOfComment (Comment oldValue, NodeText nodeText) {
+            int index;
+            List<TokenTextElement> matchingTokens = findTokenTextElementForComment((Comment) oldValue, nodeText);
+            
+            if (!matchingTokens.isEmpty()){
+                TextElement matchingElement = matchingTokens.get(0);
+                index = nodeText.findElement(matchingElement.and(matchingElement.matchByRange()));
+            } else {
+                // If no matching TokenTextElements were found, we try searching through ChildTextElements as well
+                List<ChildTextElement> matchingChilds = findChildTextElementForComment (oldValue, nodeText);
+                ChildTextElement matchingChild = matchingChilds.get(0);
+                index = nodeText.findElement(matchingChild.and(matchingChild.matchByRange()));
+            }
+            
+            return index;
+        }
+        
+        private List<ChildTextElement> findChildTextElementForComment (Comment oldValue, NodeText nodeText) {
+            List<ChildTextElement> matchingChildElements;
+            
+            matchingChildElements = nodeText.getElements().stream()
+                    .filter(e -> e.isChild())
+                    .map(c -> (ChildTextElement) c)
+                    .filter(c -> c.isComment())
+                    .filter(c -> ((Comment)c.getChild()).getContent().equals(oldValue.getContent()))
+                    .collect(Collectors.toList());
+            
+            if (matchingChildElements.size() > 1) {           
+                // Duplicate child nodes found, refine the result
+                matchingChildElements = matchingChildElements.stream()
+                    .filter(t -> isEqualRange(t.getChild().getRange(), oldValue.getRange()))
+                    .collect(Collectors.toList());
+            }
+            
+            if (matchingChildElements.size() != 1) {
+                throw new IllegalStateException("The matching child text element for the comment to be removed could not be found.");
+            }
+            
+            return matchingChildElements;
+        }
+
+        private List<TokenTextElement> findTokenTextElementForComment(Comment oldValue, NodeText nodeText) {
+            List<TokenTextElement> matchingTokens;
+            
+            if (oldValue instanceof JavadocComment) {
+                matchingTokens = nodeText.getElements().stream()
+                    .filter(e -> e.isToken(JAVADOC_COMMENT))
+                    .map(e -> (TokenTextElement) e)
+                    .filter(t -> t.getText().equals("/**" + oldValue.getContent() + "*/"))
+                    .collect(Collectors.toList());
+            } else if (oldValue instanceof BlockComment) {
+                matchingTokens = nodeText.getElements().stream()
+                    .filter(e -> e.isToken(MULTI_LINE_COMMENT))
+                    .map(e -> (TokenTextElement) e)
+                    .filter(t -> t.getText().equals("/*" + oldValue.getContent() + "*/"))
+                    .collect(Collectors.toList());
+            } else {
+                matchingTokens = nodeText.getElements().stream()
+                    .filter(e -> e.isToken(SINGLE_LINE_COMMENT))
+                    .map(e -> (TokenTextElement) e)
+                    .filter(t -> t.getText().trim().equals(("//" + oldValue.getContent()).trim()))
+                    .collect(Collectors.toList());
             }
 
-            @Override
-            public void concreteListReplacement(NodeList changedList, int index, Node oldValue, Node newValue) {
-                NodeText nodeText = getOrCreateNodeText(changedList.getParentNodeForChildren());
-                new LexicalDifferenceCalculator().calculateListReplacementDifference(findNodeListName(changedList), changedList, index, newValue).apply(nodeText, changedList.getParentNodeForChildren());
+            if (matchingTokens.size() > 1) {
+                // Duplicate comments found, refine the result
+                matchingTokens = matchingTokens.stream()
+                        .filter(t -> isEqualRange(t.getToken().getRange(), oldValue.getRange()))
+                        .collect(Collectors.toList());
             }
-        };
+            
+            return matchingTokens;
+        }
+
+
+        private boolean isEqualRange(Optional<Range> range1, Optional<Range> range2) {
+            if (range1.isPresent() && range2.isPresent()) {
+                return range1.get().equals(range2.get());
+            }
+
+            return false;
+        }
+
+        @Override
+        public void concreteListChange(NodeList changedList, AstObserver.ListChangeType type, int index, Node nodeAddedOrRemoved) {
+            NodeText nodeText = getOrCreateNodeText(changedList.getParentNodeForChildren());
+            final List<DifferenceElement> differenceElements;
+            if (type == AstObserver.ListChangeType.REMOVAL) {
+                differenceElements = LEXICAL_DIFFERENCE_CALCULATOR.calculateListRemovalDifference(findNodeListName(changedList), changedList, index);
+            } else if (type == AstObserver.ListChangeType.ADDITION) {
+                differenceElements = LEXICAL_DIFFERENCE_CALCULATOR.calculateListAdditionDifference(findNodeListName(changedList), changedList, index, nodeAddedOrRemoved);
+            } else {
+                throw new UnsupportedOperationException();
+            }
+
+            Difference difference = new Difference(differenceElements, nodeText, changedList.getParentNodeForChildren());
+            difference.apply();
+        }
+
+        @Override
+        public void concreteListReplacement(NodeList changedList, int index, Node oldValue, Node newValue) {
+            NodeText nodeText = getOrCreateNodeText(changedList.getParentNodeForChildren());
+            List<DifferenceElement> differenceElements = LEXICAL_DIFFERENCE_CALCULATOR.calculateListReplacementDifference(findNodeListName(changedList), changedList, index, newValue);
+
+            Difference difference = new Difference(differenceElements, nodeText, changedList.getParentNodeForChildren());
+            difference.apply();
+        }
     }
 
     private static void storeInitialText(Node root) {
@@ -372,10 +447,26 @@
             nodeText.addToken(JAVADOC_COMMENT, "/**" + ((JavadocComment) node).getContent() + "*/");
             return;
         }
+        if (node instanceof BlockComment) {
+            nodeText.addToken(MULTI_LINE_COMMENT, "/*" + ((BlockComment) node).getContent() + "*/");
+            return;
+        }
+        if (node instanceof LineComment) {
+            nodeText.addToken(SINGLE_LINE_COMMENT, "//" + ((LineComment) node).getContent());
+            return;
+        }
+        if (node instanceof Modifier) {
+            Modifier modifier = (Modifier)node;
+            nodeText.addToken(LexicalDifferenceCalculator.toToken(modifier), modifier.getKeyword().asString());
+            return;
+        }
 
         interpret(node, ConcreteSyntaxModel.forClass(node.getClass()), nodeText);
     }
 
+    /**
+     * TODO: Process CsmIndent and CsmUnindent before reaching this point
+     */
     private static NodeText interpret(Node node, CsmElement csm, NodeText nodeText) {
         LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(csm, node);
 
@@ -398,6 +489,20 @@
             } else if (element instanceof CsmMix) {
                 CsmMix csmMix = (CsmMix) element;
                 csmMix.getElements().forEach(e -> interpret(node, e, nodeText));
+
+            // Indentation should probably be dealt with before because an indentation has effects also on the
+            // following lines
+
+            } else if (element instanceof CsmIndent) {
+                for (int i = 0; i < Difference.STANDARD_INDENTATION_SIZE; i++) {
+                    nodeText.addToken(SPACE, " ");
+                }
+            } else if (element instanceof CsmUnindent) {
+                for (int i = 0; i < Difference.STANDARD_INDENTATION_SIZE; i++) {
+                    if (nodeText.endWithSpace()) {
+                        nodeText.removeLastElement();
+                    }
+                }
             } else {
                 throw new UnsupportedOperationException(element.getClass().getSimpleName());
             }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/NodeText.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/NodeText.java
index 1be264e..e65c5bd 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/NodeText.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/NodeText.java
@@ -21,10 +21,12 @@
 
 package com.github.javaparser.printer.lexicalpreservation;
 
+import com.github.javaparser.GeneratedJavaParserConstants;
 import com.github.javaparser.ast.Node;
 
 import java.util.LinkedList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * This contains the lexical information for a single node.
@@ -214,4 +216,23 @@
     public String toString() {
         return "NodeText{" + elements + '}';
     }
+
+    public boolean endWithSpace() {
+        if (elements.isEmpty()) {
+            return false;
+        }
+        TextElement lastElement = elements.get(elements.size() - 1);
+        if (lastElement instanceof TokenTextElement) {
+            return ((TokenTextElement)lastElement).getTokenKind() == GeneratedJavaParserConstants.SPACE;
+        } else {
+            return false;
+        }
+    }
+
+    public void removeLastElement() {
+        if (elements.isEmpty()) {
+            throw new IllegalStateException();
+        }
+        elements.remove(elements.size() - 1);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Removed.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Removed.java
new file mode 100644
index 0000000..62bbf06
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Removed.java
@@ -0,0 +1,98 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.type.PrimitiveType;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+
+public class Removed implements DifferenceElement {
+    private final CsmElement element;
+
+    Removed(CsmElement element) {
+        this.element = element;
+    }
+
+    @Override
+    public String toString() {
+        return "Removed{" + element + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Removed removed = (Removed) o;
+
+        return element.equals(removed.element);
+    }
+
+    @Override
+    public int hashCode() {
+        return element.hashCode();
+    }
+
+    @Override
+    public CsmElement getElement() {
+        return element;
+    }
+
+    public Node getChild() {
+        if (isChild()) {
+            LexicalDifferenceCalculator.CsmChild csmChild = (LexicalDifferenceCalculator.CsmChild) element;
+            return csmChild.getChild();
+        }
+
+        throw new IllegalStateException("Removed is not a " + LexicalDifferenceCalculator.CsmChild.class.getSimpleName());
+    }
+
+    public int getTokenType() {
+        if (isToken()) {
+            CsmToken csmToken = (CsmToken) element;
+            return csmToken.getTokenType();
+        }
+
+        throw new IllegalStateException("Removed is not a " + CsmToken.class.getSimpleName());
+    }
+
+    @Override
+    public boolean isAdded() {
+        return false;
+    }
+
+    public boolean isToken() { return element instanceof CsmToken; }
+
+    public boolean isChild() { return element instanceof LexicalDifferenceCalculator.CsmChild; }
+
+    public boolean isPrimitiveType() {
+        if (isChild()) {
+            LexicalDifferenceCalculator.CsmChild csmChild = (LexicalDifferenceCalculator.CsmChild) element;
+            return csmChild.getChild() instanceof PrimitiveType;
+        }
+
+        return false;
+    }
+
+    public boolean isWhiteSpace() {
+        if(isToken()) {
+            CsmToken csmToken = (CsmToken) element;
+            return csmToken.isWhiteSpace();
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isRemoved() {
+        return true;
+    }
+    
+    public boolean isNewLine() {
+        if(isToken()) {
+            CsmToken csmToken = (CsmToken) element;
+            return csmToken.isNewLine();
+        }
+
+        return false;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.java
new file mode 100644
index 0000000..0070c00
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/RemovedGroup.java
@@ -0,0 +1,227 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.JavaToken;
+import com.github.javaparser.TokenRange;
+import com.github.javaparser.TokenTypes;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * This class represents a group of {@link Removed} elements.
+ * The {@link Removed} elements are ideally consecutive for the methods in this class to work correctly.
+ *
+ * This class consists of methods that calculate information to better handle the difference application for the
+ * containing {@link Removed} elements.
+ *
+ * @see Iterable
+ *
+ * @author ThLeu
+ */
+final class RemovedGroup implements Iterable<Removed> {
+
+    private final Integer firstElementIndex;
+    private final List<Removed> removedList;
+
+    private boolean isProcessed = false;
+
+    private RemovedGroup(Integer firstElementIndex, List<Removed> removedList) {
+        if (firstElementIndex == null) {
+            throw new IllegalArgumentException("firstElementIndex should not be null");
+        }
+
+        if (removedList == null || removedList.isEmpty()) {
+            throw new IllegalArgumentException("removedList should not be null or empty");
+        }
+
+        this.firstElementIndex = firstElementIndex;
+        this.removedList = removedList;
+    }
+
+    /**
+     * Factory method to create a RemovedGroup which consists of consecutive Removed elements
+     *
+     * @param firstElementIndex the difference index at which the RemovedGroup starts
+     * @param removedList list of the consecutive Removed elements
+     * @return a RemovedGroup object
+     * @throws IllegalArgumentException if the firstElementIndex is null or the removedList is empty or null
+     */
+    public static RemovedGroup of(Integer firstElementIndex, List<Removed> removedList) {
+        return new RemovedGroup(firstElementIndex, removedList);
+    }
+
+    /**
+     * Marks the RemovedGroup as processed which indicates that it should not be processed again
+     */
+    final void processed() {
+        isProcessed = true;
+    }
+
+    /**
+     * Returns whether the RemovedGroup was already processed and should not be processed again
+     *
+     * @return wheter the RemovedGroup was already processed
+     */
+    final boolean isProcessed() {
+        return isProcessed;
+    }
+
+    private List<Integer> getIndicesBeingRemoved() {
+        return IntStream.range(firstElementIndex, firstElementIndex + removedList.size())
+                .boxed()
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Returns the difference index of the last element being removed with this RemovedGroup
+     *
+     * @return the last difference incex of this RemovedGroup
+     */
+    final Integer getLastElementIndex() {
+        List<Integer> indicesBeingRemoved = getIndicesBeingRemoved();
+        return indicesBeingRemoved.get(indicesBeingRemoved.size() - 1);
+    }
+
+    /**
+     * Returns the first element of this RemovedGroup
+     *
+     * @return the first element of this RemovedGroup
+     */
+    final Removed getFirstElement() {
+        return removedList.get(0);
+    }
+
+    /**
+     * Returns the last element of this RemovedGroup
+     *
+     * @return the last element of this RemovedGroup
+     */
+    final Removed getLastElement() {
+        return removedList.get(removedList.size() - 1);
+    }
+
+    /**
+     * Returns true if the RemovedGroup equates to a complete line
+     * This is the case if there are only spaces and tabs left on the line besides the Removed elements.
+     * <br/>
+     * Example:
+     * <pre>
+     * "  [Removed] [EOL]" -> this would be a complete line, regardless of spaces or tabs before or after the [Removed] element
+     * "  [Removed] void [EOL]" -> this would not be a complete line because of the "void"
+     * "  public [Removed] [EOL]" -> this would not be a complete line because of the "public"
+     * </pre>
+     *
+     * @return true if the RemovedGroup equates to a complete line
+     */
+    final boolean isACompleteLine() {
+        return hasOnlyWhitespace(getFirstElement(), hasOnlyWhitespaceInFrontFunction)
+                && hasOnlyWhitespace(getLastElement(), hasOnlyWhitespaceBehindFunction);
+    }
+
+    private final Function<JavaToken, Boolean> hasOnlyWhitespaceJavaTokenInFrontFunction = begin -> hasOnlyWhiteSpaceForTokenFunction(begin, token -> token.getPreviousToken());
+    private final Function<JavaToken, Boolean> hasOnlyWhitespaceJavaTokenBehindFunction = end -> hasOnlyWhiteSpaceForTokenFunction(end, token -> token.getNextToken());
+    private final Function<TokenRange, Boolean> hasOnlyWhitespaceInFrontFunction = tokenRange -> hasOnlyWhitespaceJavaTokenInFrontFunction.apply(tokenRange.getBegin());
+    private final Function<TokenRange, Boolean> hasOnlyWhitespaceBehindFunction = tokenRange -> hasOnlyWhitespaceJavaTokenBehindFunction.apply(tokenRange.getEnd());
+
+    private boolean hasOnlyWhitespace(Removed startElement, Function<TokenRange, Boolean> hasOnlyWhitespaceFunction) {
+        boolean hasOnlyWhitespace = false;
+        if (startElement.isChild()) {
+            LexicalDifferenceCalculator.CsmChild csmChild = (LexicalDifferenceCalculator.CsmChild) startElement.getElement();
+            Node child = csmChild.getChild();
+
+            Optional<TokenRange> tokenRange = child.getTokenRange();
+            if (tokenRange.isPresent()) {
+                hasOnlyWhitespace = hasOnlyWhitespaceFunction.apply(tokenRange.get());
+            }
+        } else if (startElement.isToken()) {
+            CsmToken token = (CsmToken) startElement.getElement();
+            if (TokenTypes.isEndOfLineToken(token.getTokenType())) {
+                hasOnlyWhitespace = true;
+            }
+        }
+        return hasOnlyWhitespace;
+    }
+
+    private boolean hasOnlyWhiteSpaceForTokenFunction(JavaToken token, Function<JavaToken, Optional<JavaToken>> tokenFunction) {
+        Optional<JavaToken> tokenResult = tokenFunction.apply(token);
+
+        if (tokenResult.isPresent()) {
+            if (TokenTypes.isSpaceOrTab(tokenResult.get().getKind())) {
+                return hasOnlyWhiteSpaceForTokenFunction(tokenResult.get(), tokenFunction);
+            } else if (TokenTypes.isEndOfLineToken(tokenResult.get().getKind())) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns the indentation in front of this RemovedGroup if possible.
+     * If there is something else than whitespace in front, Optional.empty() is returned.
+     *
+     * @return the indentation in front of this RemovedGroup or Optional.empty()
+     */
+    final Optional<Integer> getIndentation() {
+        Removed firstElement = getFirstElement();
+
+        int indentation = 0;
+        if (firstElement.isChild()) {
+            LexicalDifferenceCalculator.CsmChild csmChild = (LexicalDifferenceCalculator.CsmChild) firstElement.getElement();
+            Node child = csmChild.getChild();
+
+            Optional<TokenRange> tokenRange = child.getTokenRange();
+            if (tokenRange.isPresent()) {
+                JavaToken begin = tokenRange.get().getBegin();
+
+                if (hasOnlyWhitespaceJavaTokenInFrontFunction.apply(begin)) {
+                    Optional<JavaToken> previousToken = begin.getPreviousToken();
+
+                    while(previousToken.isPresent() && (TokenTypes.isSpaceOrTab(previousToken.get().getKind()))) {
+                        indentation++;
+
+                        previousToken = previousToken.get().getPreviousToken();
+                    }
+
+                    if (previousToken.isPresent()) {
+                        if (TokenTypes.isEndOfLineToken(previousToken.get().getKind())) {
+                            return Optional.of(Integer.valueOf(indentation));
+                        } else {
+                            return Optional.empty();
+                        }
+                    } else {
+                        return Optional.of(Integer.valueOf(indentation));
+                    }
+                }
+            }
+        }
+
+        return Optional.empty();
+    }
+
+    @Override
+    public final Iterator<Removed> iterator() {
+        return new Iterator<Removed>() {
+            private int currentIndex = 0;
+
+            @Override
+            public boolean hasNext() {
+                return currentIndex < removedList.size() && removedList.get(currentIndex) != null;
+            }
+
+            @Override
+            public Removed next() {
+                return removedList.get(currentIndex++);
+            }
+
+        };
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Reshuffled.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Reshuffled.java
new file mode 100644
index 0000000..652145f
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/Reshuffled.java
@@ -0,0 +1,63 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import com.github.javaparser.printer.concretesyntaxmodel.CsmMix;
+
+/**
+ * Elements in a CsmMix have been reshuffled. It could also mean that
+ * some new elements have been added or removed to the mix.
+ */
+public class Reshuffled implements DifferenceElement {
+    private final CsmMix previousOrder;
+    private final CsmMix nextOrder;
+
+    Reshuffled(CsmMix previousOrder, CsmMix nextOrder) {
+        this.previousOrder = previousOrder;
+        this.nextOrder = nextOrder;
+    }
+
+    @Override
+    public String toString() {
+        return "Reshuffled{" + nextOrder + ", previous="+ previousOrder+ '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Reshuffled that = (Reshuffled) o;
+
+        if (!previousOrder.equals(that.previousOrder)) return false;
+        return nextOrder.equals(that.nextOrder);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = previousOrder.hashCode();
+        result = 31 * result + nextOrder.hashCode();
+        return result;
+    }
+
+    @Override
+    public CsmMix getElement() {
+        return nextOrder;
+    }
+
+    public CsmMix getPreviousOrder() {
+        return previousOrder;
+    }
+
+    public CsmMix getNextOrder() {
+        return nextOrder;
+    }
+
+    @Override
+    public boolean isAdded() {
+        return false;
+    }
+
+    @Override
+    public boolean isRemoved() {
+        return false;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElement.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElement.java
index 987b8f2..6061922 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElement.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElement.java
@@ -22,8 +22,11 @@
 package com.github.javaparser.printer.lexicalpreservation;
 
 import com.github.javaparser.GeneratedJavaParserConstants;
+import com.github.javaparser.Range;
 import com.github.javaparser.ast.Node;
 
+import java.util.Optional;
+
 public abstract class TextElement implements TextElementMatcher {
 
     abstract String expand();
@@ -59,4 +62,29 @@
      * Is this TextElement representing a child of the given class?
      */
     public abstract boolean isChildOfClass(Class<? extends Node> nodeClass);
+
+    public boolean isChild() {
+        return isChildOfClass(Node.class);
+    }
+
+    abstract Optional<Range> getRange();
+
+    /**
+     * Creates a {@link TextElementMatcher} that matches any TextElement with the same range as this TextElement.<br/>
+     * This can be used to curry another TextElementMatcher.<br/>
+     * e.g. {@code someTextElementMatcher.and(textElement.matchByRange());}
+     *
+     * @return TextElementMatcher that matches any TextElement with the same Range
+     */
+    TextElementMatcher matchByRange() {
+        return (TextElement textElement) -> {
+            Optional<Range> range1 = this.getRange();
+            Optional<Range> range2 = textElement.getRange();
+            if (range1.isPresent() && range2.isPresent()) {
+                return range1.get().equals(range2.get());
+            }
+
+            return false;
+        };
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementMatcher.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementMatcher.java
index e522008..66ac926 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementMatcher.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TextElementMatcher.java
@@ -25,4 +25,14 @@
 
     boolean match(TextElement textElement);
 
+    /**
+     * This allows the combination of different TextElementMatcher instances.<br/>
+     * If combined, all of the TextElementMatchers have to return true.
+     *
+     * @param textElementMatcher TextElementMatcher to combine with this one
+     * @return A new and combined TextElementMatcher of this and textElementMatcher
+     */
+    default TextElementMatcher and(TextElementMatcher textElementMatcher) {
+        return textElement -> this.match(textElement) && textElementMatcher.match(textElement);
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java
index e57b214..bc96488 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/TokenTextElement.java
@@ -22,9 +22,11 @@
 package com.github.javaparser.printer.lexicalpreservation;
 
 import com.github.javaparser.JavaToken;
-import com.github.javaparser.TokenTypes;
+import com.github.javaparser.Range;
 import com.github.javaparser.ast.Node;
 
+import java.util.Optional;
+
 class TokenTextElement extends TextElement {
     private final JavaToken token;
 
@@ -50,7 +52,7 @@
         return token.getText();
     }
 
-    public int getTokenKind() {
+    int getTokenKind() {
         return token.getKind();
     }
 
@@ -112,4 +114,9 @@
     public boolean isChildOfClass(Class<? extends Node> nodeClass) {
         return false;
     }
+
+    @Override
+    Optional<Range> getRange() {
+        return token.getRange();
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/WrappingRangeIterator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/WrappingRangeIterator.java
new file mode 100644
index 0000000..27a7d56
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/WrappingRangeIterator.java
@@ -0,0 +1,27 @@
+package com.github.javaparser.printer.lexicalpreservation;
+
+import java.util.Iterator;
+
+public class WrappingRangeIterator implements Iterator<Integer> {
+    private final int limit;
+    private int currentValue = 0;
+
+    public WrappingRangeIterator(int limit) {
+        this.limit = limit;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return true;
+    }
+
+    @Override
+    public Integer next() {
+        int valueToReturn = currentValue;
+        ++currentValue;
+        if (currentValue == limit) {
+            currentValue = 0;
+        }
+        return valueToReturn;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java
index 23fe09d..3cb84c6 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java
@@ -13,13 +13,13 @@
     default boolean evaluate(CsmConditional csmConditional, Node node) {
         switch (csmConditional.getCondition()) {
             case FLAG:
-                return (Boolean) getValue(csmConditional.getProperty(), node);
+                return csmConditional.getProperties().stream().anyMatch(p -> (Boolean) getValue(p, node));
             case IS_NOT_EMPTY:
                 return !Utils.valueIsNullOrEmpty(getValue(csmConditional.getProperty(), node));
             case IS_EMPTY:
                 return Utils.valueIsNullOrEmpty(getValue(csmConditional.getProperty(), node));
             case IS_PRESENT:
-                return !Utils.valueIsNullOrEmpty(getValue(csmConditional.getProperty(), node));
+                return !Utils.valueIsNullOrEmptyStringOrOptional(getValue(csmConditional.getProperty(), node));
             default:
                 throw new UnsupportedOperationException("" + csmConditional.getProperty() + " " + csmConditional.getCondition());
         }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java
index c99efd2..c7cd874 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java
@@ -25,6 +25,8 @@
                 throw new IllegalStateException("Expected NodeList, found " + currentRawValue.getClass().getCanonicalName());
             }
             NodeList<?> currentNodeList = (NodeList<?>)currentRawValue;
+            // fix #2187 set the parent node in the new list
+            nodeList.setParentNode(node);
             nodeList.addAll(currentNodeList);
             nodeList.remove(index);
             return nodeList;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java
index ccb0ead..9bf1968 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java
@@ -3,7 +3,6 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.observer.ObservableProperty;
-import com.github.javaparser.utils.Pair;
 
 import java.util.Optional;
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/UnsolvedSymbolException.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/UnsolvedSymbolException.java
index b915096..be1f6b3 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/UnsolvedSymbolException.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/UnsolvedSymbolException.java
@@ -28,26 +28,52 @@
  */
 public class UnsolvedSymbolException extends RuntimeException {
 
-    private String context;
+    /**
+     * The name of the symbol that could not be resolved.
+     */
     private String name;
 
-    public UnsolvedSymbolException(String name, String context) {
-        super("Unsolved symbol in " + context + " : " + name);
-        this.context = context;
-        this.name = name;
-    }
+    /**
+     * Additional information that provides more details on the context that a symbol could not be resolved in, or
+     * {@code null} if there is no contextual information, or if the contextual information is unknown.
+     */
+    private String context;
+
+    /**
+     * The throwable that caused this {@code UnsolvedSymbolException} to get thrown, or {@code null} if this
+     * {@code UnsolvedSymbolException} was not caused by another throwable, or if the causative throwable is unknown.
+     */
+    private Throwable cause;
 
     public UnsolvedSymbolException(String name) {
-        super("Unsolved symbol : " + name);
-        this.context = "unknown";
+        this(name, null, null);
+    }
+
+    public UnsolvedSymbolException(String name, String context) {
+        this(name, context, null);
+    }
+
+    public UnsolvedSymbolException(String name, Throwable cause) {
+        this(name, null, cause);
+    }
+
+    public UnsolvedSymbolException(String name, String context, Throwable cause) {
+        super("Unsolved symbol" + (context != null ? " in " + context : "") + " : " + name, cause);
         this.name = name;
+        this.context = context;
+        this.cause = cause;
+    }
+
+    public String getName() {
+        return name;
     }
 
     @Override
     public String toString() {
         return "UnsolvedSymbolException{" +
-                "context='" + context + '\'' +
-                ", name='" + name + '\''+
-                '}';
+               "context='" + context + "'" +
+               ", name='" + name + "'" +
+               ", cause='" + cause + "'" +
+               "}";
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/AssociableToAST.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/AssociableToAST.java
new file mode 100644
index 0000000..0346fbb
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/AssociableToAST.java
@@ -0,0 +1,37 @@
+package com.github.javaparser.resolution.declarations;
+
+import com.github.javaparser.ast.Node;
+
+import java.util.Optional;
+
+/**
+ * A declaration that can be potentially associated with an AST node.
+ * @param <N> type of AST Node that can be associated
+ */
+public interface AssociableToAST<N extends Node> {
+
+    /**
+     * If the declaration is associated to an AST node return it, otherwise it return empty.
+     * Declaration based on source code have an AST node associated while others don't. Example
+     * of other declarations are declarations coming from reflection or JARs.
+     *
+     * You may wonder how this method is different from the various getWrappedNode.
+     * The difference is that toAst is present in all Resolved* declarations (such as
+     * ResolvedAnnotationDeclaration), while getWrappedNode is present
+     * only on the subclasses of the Resolved* declarations that derive from JP AST nodes (such as
+     * JavaParserClassDeclaration). Therefore one
+     * which has a Resolved* declaration need to do a downcast before being able to use getWrappedNode.
+     *
+     * Now, this means that toAst could potentially replace getWrappedNode (but not the other way around!).
+     * However toAst return an Optional, which is less convenient than getting the direct node. Also,
+     * toAst sometimes have to return a more generic node. This is the case for subclasses of
+     * ResolvedClassDeclaration. In those cases toAst return a Node. Why? Because both anonymous
+     * class declarations and standard class declarations are subclasses of that. In one case the
+     * underlying AST node is an ObjectCreationExpr, while in the other case it is ClassOrInterfaceDeclaration.
+     * In these cases getWrappedNode is particularly nice because it returns the right type of AST node,
+     * not just a Node.
+     */
+    default Optional<N> toAst() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/HasAccessSpecifier.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/HasAccessSpecifier.java
index 5d7e5bb..6b0d10c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/HasAccessSpecifier.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/HasAccessSpecifier.java
@@ -27,6 +27,7 @@
  * Anything which can have an AccessSpecifier.
  *
  * @author Federico Tomassetti
+ * @see AccessSpecifier
  */
 public interface HasAccessSpecifier {
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedAnnotationDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedAnnotationDeclaration.java
index c3124f2..b8da2ee 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedAnnotationDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedAnnotationDeclaration.java
@@ -21,12 +21,15 @@
 
 package com.github.javaparser.resolution.declarations;
 
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+
 import java.util.List;
 
 /**
  * @author Federico Tomassetti
  */
-public interface ResolvedAnnotationDeclaration extends ResolvedReferenceTypeDeclaration {
+public interface ResolvedAnnotationDeclaration extends ResolvedReferenceTypeDeclaration,
+        AssociableToAST<AnnotationDeclaration> {
 
     List<ResolvedAnnotationMemberDeclaration> getAnnotationMembers();
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedClassDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedClassDeclaration.java
index 08a8d75..cc99cf1 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedClassDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedClassDeclaration.java
@@ -21,6 +21,7 @@
 
 package com.github.javaparser.resolution.declarations;
 
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 
 import java.util.List;
@@ -28,10 +29,13 @@
 /**
  * Declaration of a Class (not an interface or an enum).
  *
+ * Note that it can be associated to a Node AST because anonymous class declarations return an incompatible
+ * node type, compared to classic class declarations.
+ *
  * @author Federico Tomassetti
  */
 public interface ResolvedClassDeclaration extends ResolvedReferenceTypeDeclaration,
-        ResolvedTypeParametrizable, HasAccessSpecifier {
+        ResolvedTypeParametrizable, HasAccessSpecifier, AssociableToAST<Node> {
 
     /**
      * This method should always return true.
@@ -80,6 +84,7 @@
      * List of constructors available for the class.
      * This list should also include the default constructor.
      */
+    @Override
     List<ResolvedConstructorDeclaration> getConstructors();
 
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedConstructorDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedConstructorDeclaration.java
index 07f486c..92cb67b 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedConstructorDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedConstructorDeclaration.java
@@ -21,12 +21,15 @@
 
 package com.github.javaparser.resolution.declarations;
 
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+
 /**
  * A declaration of a constructor.
  *
  * @author Federico Tomassetti
  */
-public interface ResolvedConstructorDeclaration extends ResolvedMethodLikeDeclaration {
+public interface ResolvedConstructorDeclaration extends ResolvedMethodLikeDeclaration,
+        AssociableToAST<ConstructorDeclaration> {
 
     /**
      * A constructor can be declared in a class or an enum.
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedDeclaration.java
index 86bee80..4df99ce 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedDeclaration.java
@@ -36,7 +36,7 @@
     }
 
     /**
-     * Should return the name or throw a RuntimeException if the name is not available.
+     * Should return the name or return null if the name is not available.
      */
     String getName();
 
@@ -48,6 +48,17 @@
     }
 
     /**
+     * Does this declaration represents a variable?
+     */
+    default boolean isVariable() {
+        return false;
+    }
+
+    default boolean isEnumConstant() {
+        return false;
+    }
+
+    /**
      * Does this declaration represents a method parameter?
      */
     default boolean isParameter() {
@@ -95,4 +106,8 @@
     default ResolvedMethodDeclaration asMethod() {
         throw new UnsupportedOperationException(String.format("%s is not a MethodDeclaration", this));
     }
+
+    default ResolvedEnumConstantDeclaration asEnumConstant() {
+        throw new UnsupportedOperationException(String.format("%s is not an EnumConstantDeclaration", this));
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumConstantDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumConstantDeclaration.java
index aeb0ded..62b16f9 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumConstantDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumConstantDeclaration.java
@@ -27,4 +27,14 @@
 public interface ResolvedEnumConstantDeclaration extends ResolvedValueDeclaration {
 
     String getName();
+
+    @Override
+    default boolean isEnumConstant() {
+        return true;
+    }
+
+    @Override
+    default ResolvedEnumConstantDeclaration asEnumConstant() {
+        return this;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumDeclaration.java
index e31a4fb..c4e4c72 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedEnumDeclaration.java
@@ -42,4 +42,13 @@
     }
 
     List<ResolvedEnumConstantDeclaration> getEnumConstants();
+
+    default boolean hasEnumConstant(String name) {
+        return getEnumConstants().stream().anyMatch(c -> c.getName().equals(name));
+    }
+
+    default ResolvedEnumConstantDeclaration getEnumConstant(final String name) {
+        return getEnumConstants().stream().filter(c -> c.getName().equals(name)).findFirst()
+                .orElseThrow(() -> new IllegalArgumentException("No constant named " + name));
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedInterfaceDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedInterfaceDeclaration.java
index 5ef53b2..881709f 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedInterfaceDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedInterfaceDeclaration.java
@@ -21,6 +21,7 @@
 
 package com.github.javaparser.resolution.declarations;
 
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 
 import java.util.ArrayList;
@@ -32,7 +33,7 @@
  * @author Federico Tomassetti
  */
 public interface ResolvedInterfaceDeclaration extends ResolvedReferenceTypeDeclaration,
-        ResolvedTypeParametrizable, HasAccessSpecifier {
+        ResolvedTypeParametrizable, HasAccessSpecifier, AssociableToAST<ClassOrInterfaceDeclaration> {
 
     @Override
     default boolean isInterface() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java
index 9f2f64c..a1319da 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java
@@ -21,6 +21,7 @@
 
 package com.github.javaparser.resolution.declarations;
 
+import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
 
 /**
@@ -28,7 +29,7 @@
  *
  * @author Federico Tomassetti
  */
-public interface ResolvedMethodDeclaration extends ResolvedMethodLikeDeclaration {
+public interface ResolvedMethodDeclaration extends ResolvedMethodLikeDeclaration, AssociableToAST<MethodDeclaration> {
 
     /**
      * The type of the value returned by the current method. This method can also be invoked
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java
index 6686522..b277adb 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedParameterDeclaration.java
@@ -33,6 +33,13 @@
         return true;
     }
 
+    /**
+     * Necessary because parameters obtained through reflection could not have a name.
+     */
+    default boolean hasName() {
+        return true;
+    }
+
     @Override
     default ResolvedParameterDeclaration asParameter() {
         return this;
@@ -45,7 +52,7 @@
 
     /**
      * Describe the type of the parameter. In practice add three dots to the type name
-     * is the parameter is variadic.
+     * if the parameter is variadic.
      */
     default String describeType() {
         if (isVariadic()) {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java
index b395210..d959d33 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java
@@ -22,6 +22,7 @@
 package com.github.javaparser.resolution.declarations;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
@@ -37,7 +38,7 @@
  * @author Federico Tomassetti
  */
 public interface ResolvedReferenceTypeDeclaration extends ResolvedTypeDeclaration,
-        ResolvedTypeParametrizable {
+                                                                  ResolvedTypeParametrizable {
 
     @Override
     default ResolvedReferenceTypeDeclaration asReferenceType() {
@@ -49,14 +50,41 @@
     ///
 
     /**
-     * The list of all the direct ancestors of the current declaration.
-     * Note that the ancestor can be parametrized types with values specified. For example:
+     * Resolves the types of all direct ancestors (i.e., the directly extended class and the directly implemented
+     * interfaces) and returns the list of ancestors as a list of resolved reference types.
+     * <p>
+     * In case any ancestor cannot be resolved, an {@code UnsolvedSymbolException} is thrown. In order to obtain a list
+     * of only the resolvable direct ancestors, use {@link #getAncestors(boolean)} and pass the value {@code true}.
+     * <p>
+     * Note that an ancestor can be parametrized types with values specified. For example:
      * <p>
      * class A implements Comparable&lt;String&gt; {}
      * <p>
      * In this case the ancestor is Comparable&lt;String&gt;
+     *
+     * @return The list of resolved ancestors.
+     * @throws UnsolvedSymbolException if some ancestor could not be resolved.
      */
-    List<ResolvedReferenceType> getAncestors();
+    default List<ResolvedReferenceType> getAncestors() {
+        return getAncestors(false);
+    }
+
+    /**
+     * Resolves the types of all direct ancestors (i.e., the directly extended class and the directly implemented
+     * interfaces) and returns the list of ancestors as a list of resolved reference types.
+     * <p>
+     * If {@code acceptIncompleteList} is {@code false}, then an {@code UnsolvedSymbolException} is thrown if any
+     * ancestor cannot be resolved. Otherwise, a list of only the resolvable direct ancestors is returned.
+     *
+     * @param acceptIncompleteList When set to {@code false}, this method throws an {@link UnsolvedSymbolException} if
+     *                             one or more ancestor could not be resolved. When set to {@code true}, this method
+     *                             does not throw an {@link UnsolvedSymbolException}, but the list of returned ancestors
+     *                             may be incomplete in case one or more ancestor could not be resolved.
+     * @return The list of resolved ancestors.
+     * @throws UnsolvedSymbolException if some ancestor could not be resolved and {@code acceptIncompleteList} is set to
+     *                                 {@code false}.
+     */
+    List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList);
 
     /**
      * The list of all the ancestors of the current declaration, direct and indirect.
@@ -65,9 +93,9 @@
     default List<ResolvedReferenceType> getAllAncestors() {
         List<ResolvedReferenceType> ancestors = new ArrayList<>();
         // We want to avoid infinite recursion in case of Object having Object as ancestor
-        if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) {       
+        if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) {
             for (ResolvedReferenceType ancestor : getAncestors()) {
-                ancestors.add(ancestor);    
+                ancestors.add(ancestor);
                 for (ResolvedReferenceType inheritedAncestor : ancestor.getAllAncestors()) {
                     if (!ancestors.contains(inheritedAncestor)) {
                         ancestors.add(inheritedAncestor);
@@ -118,14 +146,14 @@
      * Has this type a field with the given name?
      */
     default boolean hasField(String name) {
-        return this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent();
+        return this.getAllFields().stream().anyMatch(f -> f.getName().equals(name));
     }
 
     /**
      * Either a declared field or inherited field which is not private.
      */
     default boolean hasVisibleField(String name) {
-        return getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent();
+        return getVisibleFields().stream().anyMatch(f -> f.getName().equals(name));
     }
 
     /**
@@ -138,8 +166,8 @@
      */
     default List<ResolvedFieldDeclaration> getVisibleFields() {
         return getAllFields().stream()
-                .filter(f -> f.declaringType().equals(this) || f.accessSpecifier() != AccessSpecifier.PRIVATE)
-                .collect(Collectors.toList());
+                       .filter(f -> f.declaringType().equals(this) || f.accessSpecifier() != AccessSpecifier.PRIVATE)
+                       .collect(Collectors.toList());
     }
 
     /**
@@ -160,7 +188,8 @@
      * Return a list of all the fields declared in this type.
      */
     default List<ResolvedFieldDeclaration> getDeclaredFields() {
-        return getAllFields().stream().filter(it -> it.declaringType().getQualifiedName().equals(getQualifiedName())).collect(Collectors.toList());
+        return getAllFields().stream().filter(it -> it.declaringType().getQualifiedName()
+                                                            .equals(getQualifiedName())).collect(Collectors.toList());
     }
 
     ///
@@ -243,4 +272,6 @@
         }
         return Optional.empty();
     }
+
+    List<ResolvedConstructorDeclaration> getConstructors();
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeDeclaration.java
index 0b715fe..91d7005 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeDeclaration.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeDeclaration.java
@@ -67,8 +67,6 @@
 
     /**
      * Get the ReferenceTypeDeclaration enclosing this declaration.
-     *
-     * @return
      */
     Optional<ResolvedReferenceTypeDeclaration> containerType();
 
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java
index 4a7e292..c572031 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedPrimitiveType.java
@@ -48,7 +48,7 @@
     private String boxTypeQName;
     private List<ResolvedPrimitiveType> promotionTypes;
 
-    private ResolvedPrimitiveType(String name, String boxTypeQName, List<ResolvedPrimitiveType> promotionTypes) {
+    ResolvedPrimitiveType(String name, String boxTypeQName, List<ResolvedPrimitiveType> promotionTypes) {
         this.name = name;
         this.boxTypeQName = boxTypeQName;
         this.promotionTypes = promotionTypes;
@@ -114,10 +114,8 @@
                 }
             }
             return false;
-        } else if (other.isConstraint()){
-            return this.isAssignableBy(other.asConstraintType().getBound());
         } else {
-            return false;
+            return other.isConstraint() && this.isAssignableBy(other.asConstraintType().getBound());
         }
     }
 
@@ -125,4 +123,7 @@
         return boxTypeQName;
     }
 
+    public boolean isNumeric() {
+        return this != BOOLEAN;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java
index 4fecaf6..80bebcd 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java
@@ -21,7 +21,10 @@
 
 package com.github.javaparser.resolution.types;
 
+import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParameterValueProvider;
@@ -32,6 +35,8 @@
 import java.util.*;
 import java.util.stream.Collectors;
 
+import static com.github.javaparser.ast.Modifier.Keyword.PRIVATE;
+
 /**
  * A ReferenceType like a class, an interface or an enum. Note that this type can contain also the values
  * specified for the type parameters.
@@ -57,6 +62,9 @@
     }
 
     public ResolvedReferenceType(ResolvedReferenceTypeDeclaration typeDeclaration, List<ResolvedType> typeArguments) {
+        if (typeDeclaration == null) {
+            throw new IllegalArgumentException("TypeDeclaration is not expected to be null");
+        }
         if (typeDeclaration.isTypeParameter()) {
             throw new IllegalArgumentException("You should use only Classes, Interfaces and enums");
         }
@@ -155,7 +163,7 @@
 
     @Override
     public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, ResolvedType replaced,
-                                     Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) {
+                                             Map<ResolvedTypeParameterDeclaration, ResolvedType> inferredTypes) {
         if (replaced == null) {
             throw new IllegalArgumentException();
         }
@@ -179,7 +187,7 @@
 
         List<ResolvedType> values = result.typeParametersValues();
         // FIXME
-        if(values.contains(tpToReplace)){
+        if (values.contains(tpToReplace)) {
             int index = values.indexOf(tpToReplace);
             values.set(index, replaced);
             return create(result.getTypeDeclaration(), values);
@@ -217,6 +225,13 @@
      */
     public abstract List<ResolvedReferenceType> getAllAncestors();
 
+    /**
+     * Return direct ancestors, that means the superclasses and interfaces implemented directly.
+     * This list should include Object if the class has no other superclass or the interface is not extending another interface.
+     * There is an exception for Object itself.
+     */
+    public abstract List<ResolvedReferenceType> getDirectAncestors();
+
     public final List<ResolvedReferenceType> getAllInterfacesAncestors() {
         return getAllAncestors().stream()
                 .filter(it -> it.getTypeDeclaration().isInterface())
@@ -261,9 +276,9 @@
     public List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> getTypeParametersMap() {
         List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typeParametersMap = new ArrayList<>();
         if (!isRawType()) {
-	        for (int i = 0; i < typeDeclaration.getTypeParameters().size(); i++) {
-	            typeParametersMap.add(new Pair<>(typeDeclaration.getTypeParameters().get(0), typeParametersValues().get(i)));
-	        }
+            for (int i = 0; i < typeDeclaration.getTypeParameters().size(); i++) {
+                typeParametersMap.add(new Pair<>(typeDeclaration.getTypeParameters().get(i), typeParametersValues().get(i)));
+            }
         }
         return typeParametersMap;
     }
@@ -323,6 +338,11 @@
      */
     public abstract Set<MethodUsage> getDeclaredMethods();
 
+    /**
+     * Fields declared on this type.
+     */
+    public abstract Set<ResolvedFieldDeclaration> getDeclaredFields();
+
     public boolean isRawType() {
         if (!typeDeclaration.getTypeParameters().isEmpty()) {
             if (typeParametersMap().isEmpty()) {
@@ -330,9 +350,7 @@
             }
             for (String name : typeParametersMap().getNames()) {
                 Optional<ResolvedType> value = typeParametersMap().getValueBySignature(name);
-                if (value.isPresent() && value.get().isTypeVariable() && value.get().asTypeVariable().qualifiedName().equals(name)) {
-                    // nothing to do
-                } else {
+                if (!value.isPresent() || !value.get().isTypeVariable() || !value.get().asTypeVariable().qualifiedName().equals(name)) {
                     return false;
                 }
             }
@@ -359,6 +377,39 @@
 
     public abstract ResolvedType toRawType();
 
+    /**
+     * Get a list of all the methods available on this type. This list includes methods declared in this type and
+     * methods inherited. This list includes methods of all sort of visibility. However it does not include methods
+     * that have been overwritten.
+     */
+    public List<ResolvedMethodDeclaration> getAllMethods() {
+        List<ResolvedMethodDeclaration> allMethods = new LinkedList<>(this.getTypeDeclaration().getDeclaredMethods());
+        getDirectAncestors().forEach(a ->
+                allMethods.addAll(a.getAllMethods()));
+        return allMethods;
+    }
+
+    /**
+     * Fields which are visible to inheritors. They include all inherited fields which are visible to this
+     * type plus all declared fields which are not private.
+     */
+    public List<ResolvedFieldDeclaration> getAllFieldsVisibleToInheritors() {
+        List<ResolvedFieldDeclaration> res = new LinkedList<>(this.getDeclaredFields().stream()
+                .filter(f -> f.accessSpecifier() != AccessSpecifier.PRIVATE)
+                .collect(Collectors.toList()));
+
+        getDirectAncestors().forEach(a ->
+                res.addAll(a.getAllFieldsVisibleToInheritors()));
+
+        return res;
+    }
+
+    public List<ResolvedMethodDeclaration> getAllMethodsVisibleToInheritors() {
+        return this.getAllMethods().stream()
+                .filter(m -> m.accessSpecifier() != AccessSpecifier.PRIVATE)
+                .collect(Collectors.toList());
+    }
+
     //
     // Protected methods
     //
@@ -424,11 +475,9 @@
                         }
                     } else {
                         if (thisParam instanceof ResolvedTypeVariable && otherParam instanceof ResolvedTypeVariable) {
-                            List<ResolvedType> thisBounds = thisParam.asTypeVariable().asTypeParameter().getBounds().stream().map(bound -> bound.getType()).collect(Collectors.toList());
-                            List<ResolvedType> otherBounds = otherParam.asTypeVariable().asTypeParameter().getBounds().stream().map(bound -> bound.getType()).collect(Collectors.toList());
-                            if (thisBounds.size() == otherBounds.size() && otherBounds.containsAll(thisBounds)) {
-                                return true;
-                            }
+                            List<ResolvedType> thisBounds = thisParam.asTypeVariable().asTypeParameter().getBounds().stream().map(ResolvedTypeParameterDeclaration.Bound::getType).collect(Collectors.toList());
+                            List<ResolvedType> otherBounds = otherParam.asTypeVariable().asTypeParameter().getBounds().stream().map(ResolvedTypeParameterDeclaration.Bound::getType).collect(Collectors.toList());
+                            return thisBounds.size() == otherBounds.size() && otherBounds.containsAll(thisBounds);
                         }
                         return false;
                     }
@@ -444,7 +493,14 @@
     //
 
     private static List<ResolvedType> deriveParams(ResolvedReferenceTypeDeclaration typeDeclaration) {
-        return typeDeclaration.getTypeParameters().stream().map((tp) -> new ResolvedTypeVariable(tp)).collect(Collectors.toList());
+        if (typeDeclaration == null) {
+            throw new IllegalArgumentException("TypeDeclaration is not expected to be null");
+        }
+        List<ResolvedTypeParameterDeclaration> typeParameters = typeDeclaration.getTypeParameters();
+        if (typeParameters == null) {
+            throw new RuntimeException("Type parameters are not expected to be null");
+        }
+        return typeParameters.stream().map(ResolvedTypeVariable::new).collect(Collectors.toList());
     }
 
     public abstract ResolvedReferenceType deriveTypeParameters(ResolvedTypeParametersMap typeParametersMap);
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java
index 5e91057..bd61e2c 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java
@@ -42,7 +42,7 @@
 
     @Override
     public String toString() {
-        return "TypeVariable {" + typeParameter.getQualifiedName() + "}";
+        return "TypeVariable {" + typeParameter.toString() + "}";
     }
 
     public String qualifiedName() {
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java
index bd5361a..7a673e4 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedUnionType.java
@@ -21,10 +21,7 @@
 
 package com.github.javaparser.resolution.types;
 
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -42,6 +39,18 @@
         this.elements = new LinkedList<>(elements);
     }
 
+    public Optional<ResolvedReferenceType> getCommonAncestor() {
+        Optional<List<ResolvedReferenceType>> reduce = elements.stream()
+                .map(ResolvedType::asReferenceType)
+                .map(ResolvedReferenceType::getAllAncestors)
+                .reduce((a, b) -> {
+                    ArrayList<ResolvedReferenceType> common = new ArrayList<>(a);
+                    common.retainAll(b);
+                    return common;
+                });
+        return reduce.orElse(new ArrayList<>()).stream().findFirst();
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java b/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java
index 098920b..da42989 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/CodeGenerationUtils.java
@@ -8,6 +8,9 @@
 import static com.github.javaparser.utils.Utils.capitalize;
 import static com.github.javaparser.utils.Utils.decapitalize;
 
+/**
+ * Utilities that can be useful when generating code.
+ */
 public final class CodeGenerationUtils {
     private CodeGenerationUtils() {
     }
@@ -83,7 +86,7 @@
      * Converts a package name like "com.laamella.parser" to a path like "com/laamella/parser"
      */
     public static String packageToPath(String pkg) {
-        return pkg.replace(".", File.separator);
+        return pkg.replace('.', File.separatorChar);
     }
 
     /**
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java
new file mode 100644
index 0000000..aa6ad25
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/CollectionStrategy.java
@@ -0,0 +1,37 @@
+package com.github.javaparser.utils;
+
+import com.github.javaparser.ParseProblemException;
+import com.github.javaparser.ast.CompilationUnit;
+
+import java.io.FileNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.util.Optional;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+
+/**
+ * A strategy for discovering the structure of a project.
+ * Implementations could read a pom.xml, a Gradle build file, a makefile...
+ */
+public interface CollectionStrategy {
+
+    ProjectRoot collect(Path path);
+
+    default Optional<Path> getRoot(Path file) throws FileNotFoundException {
+        try {
+            return parse(file.toFile()).getStorage()
+                    .map(CompilationUnit.Storage::getSourceRoot);
+        } catch (ParseProblemException e) {
+            Log.info("Problem parsing file %s", () -> file);
+        } catch (RuntimeException e) {
+            Log.info("Could not parse file %s", () -> file);
+        }
+        return Optional.empty();
+    }
+
+    default PathMatcher getPathMatcher(String pattern) {
+        return FileSystems.getDefault().getPathMatcher(pattern);
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/Log.java b/javaparser-core/src/main/java/com/github/javaparser/utils/Log.java
index 12a9cdc..cb67a9f 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/Log.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/Log.java
@@ -3,11 +3,14 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.function.Supplier;
 
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 
 /**
  * To avoid dependencies on logging frameworks, we have invented yet another logging framework :-)
+ * <p>
+ * See <a href="http://javaparser.org/javaparsers-logging-framework-in-one-file/">a blog about this</a>
  */
 public class Log {
     /**
@@ -15,17 +18,19 @@
      */
     public static class StandardOutStandardErrorAdapter implements Adapter {
         @Override
-        public void info(String message) {
-            System.out.println(message);
+        public void info(Supplier<String> messageSupplier) {
+            System.out.println(messageSupplier.get());
         }
 
         @Override
-        public void trace(String message) {
-            System.out.println(message);
+        public void trace(Supplier<String> messageSupplier) {
+            System.out.println(messageSupplier.get());
         }
 
         @Override
-        public void error(Throwable throwable, String message) {
+        public void error(Supplier<Throwable> throwableSupplier, Supplier<String> messageSupplier) {
+            Throwable throwable = throwableSupplier.get();
+            String message = messageSupplier.get();
             if (message == null) {
                 System.err.println(throwable.getMessage());
                 printStackTrace(throwable);
@@ -40,7 +45,7 @@
         private void printStackTrace(Throwable throwable) {
             try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
                 throwable.printStackTrace(pw);
-                trace(sw.toString());
+                trace(sw::toString);
             } catch (IOException e) {
                 throw new AssertionError("Error in logging library");
             }
@@ -52,28 +57,28 @@
      */
     public static class SilentAdapter implements Adapter {
         @Override
-        public void info(String message) {
+        public void info(Supplier<String> messageSupplier) {
         }
 
         @Override
-        public void trace(String message) {
+        public void trace(Supplier<String> messageSupplier) {
         }
 
         @Override
-        public void error(Throwable throwable, String f) {
+        public void error(Supplier<Throwable> throwableSupplier, Supplier<String> messageSupplier) {
         }
     }
 
     public interface Adapter {
 
-        void info(String message);
+        void info(Supplier<String> message);
 
-        void trace(String message);
+        void trace(Supplier<String> message);
 
         /**
-         * Both can be null.
+         * Both can supply a null.
          */
-        void error(Throwable throwable, String f);
+        void error(Supplier<Throwable> throwableSupplier, Supplier<String> messageSupplier);
     }
 
     private static Adapter CURRENT_ADAPTER = new SilentAdapter();
@@ -88,35 +93,50 @@
     /**
      * For logging information that may help solving a problem.
      */
-    public static void trace(String format, Object... args) {
-        CURRENT_ADAPTER.trace(f(format, args));
+    @SafeVarargs
+    public static void trace(String format, Supplier<Object>... args) {
+        CURRENT_ADAPTER.trace(makeFormattingSupplier(format, args));
     }
 
+    private static Supplier<String> makeFormattingSupplier(String format, Supplier<Object>[] args) {
+        return () -> {
+            Object[] objects = new Object[args.length];
+            for (int i = 0; i < args.length; i++) {
+                objects[i] = args[i].get();
+            }
+            return f(format, objects);
+        };
+    }
+
+
     /**
      * For logging things that are nice to see scrolling by.
      */
-    public static void info(String format, Object... args) {
-        CURRENT_ADAPTER.info(f(format, args));
+    @SafeVarargs
+    public static void info(String format, Supplier<Object>... args) {
+        CURRENT_ADAPTER.info(makeFormattingSupplier(format, args));
     }
 
     /**
      * For drawing attention to an error.
      */
     public static void error(Throwable throwable) {
-        CURRENT_ADAPTER.error(throwable, null);
+        CURRENT_ADAPTER.error(() -> throwable, null);
     }
 
     /**
      * For drawing attention to an error that you don't have an exception for.
      */
-    public static void error(Throwable throwable, String format, Object... args) {
-        CURRENT_ADAPTER.error(throwable, f(format, args));
+    @SafeVarargs
+    public static void error(Throwable throwable, String format, Supplier<Object>... args) {
+        CURRENT_ADAPTER.error(() -> throwable, makeFormattingSupplier(format, args));
     }
 
     /**
      * For drawing attention to an error that you don't have an exception for.
      */
-    public static void error(String format, Object... args) {
-        CURRENT_ADAPTER.error(null, f(format, args));
+    @SafeVarargs
+    public static void error(String format, Supplier<Object>... args) {
+        CURRENT_ADAPTER.error(() -> null, makeFormattingSupplier(format, args));
     }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/Pair.java b/javaparser-core/src/main/java/com/github/javaparser/utils/Pair.java
index 6f84a7b..c9933cc 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/Pair.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/Pair.java
@@ -21,6 +21,8 @@
 
 package com.github.javaparser.utils;
 
+import java.util.Objects;
+
 import static com.github.javaparser.utils.CodeGenerationUtils.f;
 
 /**
@@ -45,8 +47,8 @@
 
         Pair<?, ?> pair = (Pair<?, ?>) o;
 
-        if (a != null ? !a.equals(pair.a) : pair.a != null) return false;
-        if (b != null ? !b.equals(pair.b) : pair.b != null) return false;
+        if (!Objects.equals(a, pair.a)) return false;
+        if (!Objects.equals(b, pair.b)) return false;
 
         return true;
     }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/ParserCollectionStrategy.java b/javaparser-core/src/main/java/com/github/javaparser/utils/ParserCollectionStrategy.java
new file mode 100644
index 0000000..eafefbd
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/ParserCollectionStrategy.java
@@ -0,0 +1,72 @@
+package com.github.javaparser.utils;
+
+import com.github.javaparser.ParserConfiguration;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import static java.nio.file.FileVisitResult.*;
+
+/**
+ * A brute force {@link CollectionStrategy} for discovering a project structure.
+ * It will search through the given project root path for Java files,
+ * look at their package declarations, and figure out the root directories for those files.
+ * No project definition files like pom.xml or build.gradle are used.
+ * This strategy is crude, but can work for many cases.
+ * Note that any build artifacts will also be detected: jar files in target directories and so on.
+ */
+public class ParserCollectionStrategy implements CollectionStrategy {
+
+    private final ParserConfiguration parserConfiguration;
+
+    public ParserCollectionStrategy() {
+        this(new ParserConfiguration());
+    }
+
+    public ParserCollectionStrategy(ParserConfiguration parserConfiguration) {
+        this.parserConfiguration = parserConfiguration;
+    }
+
+    @Override
+    public ProjectRoot collect(Path path) {
+        ProjectRoot projectRoot = new ProjectRoot(path, parserConfiguration);
+        try {
+            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+                Path current_root;
+                PathMatcher javaMatcher = getPathMatcher("glob:**.java");
+
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    if (javaMatcher.matches(file)) {
+                        current_root = getRoot(file).orElse(null);
+                        if (current_root != null) {
+                            return SKIP_SIBLINGS;
+                        }
+                    }
+                    return CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+                    if (Files.isHidden(dir) || (current_root != null && dir.startsWith(current_root))) {
+                        return SKIP_SUBTREE;
+                    }
+                    return CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
+                    if (current_root != null && Files.isSameFile(dir, current_root)) {
+                        projectRoot.addSourceRoot(dir);
+                        current_root = null;
+                    }
+                    return CONTINUE;
+                }
+            });
+        } catch (IOException e) {
+            Log.error(e, "Unable to walk %s", () -> path);
+        }
+        return projectRoot;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java b/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java
index 6852b29..26c6c38 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java
@@ -131,9 +131,9 @@
         final Range containedRange = contained.getRange().get();
         final Range containerRange = container.getRange().get();
         if (!ignoringAnnotations || PositionUtils.getLastAnnotation(container) == null) {
-            return container.containsWithin(contained);
+            return container.containsWithinRange(contained);
         }
-        if (!container.containsWithin(contained)) {
+        if (!container.containsWithinRange(contained)) {
             return false;
         }
         // if the node is contained, but it comes immediately after the annotations,
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/ProjectRoot.java b/javaparser-core/src/main/java/com/github/javaparser/utils/ProjectRoot.java
new file mode 100644
index 0000000..f9d428e
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/ProjectRoot.java
@@ -0,0 +1,54 @@
+package com.github.javaparser.utils;
+
+import com.github.javaparser.ParserConfiguration;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * The structure of a Java project directory.
+ * It was originally created specifically to quickly configure the symbol solver.
+ * You can use it as a general container for project information.
+ * <p/>A project has a root directory, and it has zero or more directories that contain source code.
+ * <p/>To create a ProjectRoot use a CollectionStrategy, or instantiate ProjectRoot yourself.
+ */
+public class ProjectRoot {
+
+    private final Path root;
+    private final Map<Path, SourceRoot> cache = new ConcurrentHashMap<>();
+    private final ParserConfiguration parserConfiguration;
+
+    public ProjectRoot(Path root) {
+        this(root, new ParserConfiguration());
+    }
+
+    public ProjectRoot(Path root, ParserConfiguration parserConfiguration) {
+        this.root = root;
+        this.parserConfiguration = parserConfiguration;
+    }
+
+    public Optional<SourceRoot> getSourceRoot(Path sourceRoot) {
+        return Optional.ofNullable(cache.get(sourceRoot));
+    }
+
+    public List<SourceRoot> getSourceRoots() {
+        return new ArrayList<>(cache.values());
+    }
+
+    public void addSourceRoot(Path path) {
+        cache.put(path, new SourceRoot(path).setParserConfiguration(parserConfiguration));
+    }
+
+    public Path getRoot() {
+        return root;
+    }
+
+    @Override
+    public String toString() {
+        return "ProjectRoot at " + root + " with " + cache.values().toString();
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java
index 02a90ff..44efe98 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceRoot.java
@@ -8,6 +8,7 @@
 import com.github.javaparser.printer.PrettyPrinter;
 
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -25,16 +26,14 @@
 
 import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
 import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.CodeGenerationUtils.fileInPackageRelativePath;
-import static com.github.javaparser.utils.CodeGenerationUtils.packageAbsolutePath;
-import static com.github.javaparser.utils.SourceRoot.Callback.Result.SAVE;
+import static com.github.javaparser.utils.CodeGenerationUtils.*;
 import static com.github.javaparser.utils.Utils.assertNotNull;
-import static java.nio.file.FileVisitResult.CONTINUE;
-import static java.nio.file.FileVisitResult.SKIP_SUBTREE;
+import static java.nio.file.FileVisitResult.*;
 
 /**
- * A collection of Java source files located in one directory and its subdirectories on the file system. Files can be
- * parsed and written back one by one or all together. <b>Note that</b> the internal cache used is thread-safe.
+ * A collection of Java source files located in one directory and its subdirectories on the file system. The root directory
+ * corresponds to the root of the package structure of the source files within. Files can be parsed and written back one
+ * by one or all together. <b>Note that</b> the internal cache used is thread-safe.
  * <ul>
  * <li>methods called "tryToParse..." will return their result inside a "ParseResult", which supports parse successes and failures.</li>
  * <li>methods called "parse..." will return "CompilationUnit"s. If a file fails to parse, an exception is thrown.</li>
@@ -45,7 +44,7 @@
     @FunctionalInterface
     public interface Callback {
         enum Result {
-            SAVE, DONT_SAVE
+            SAVE, DONT_SAVE, TERMINATE
         }
 
         /**
@@ -62,33 +61,26 @@
     private Function<CompilationUnit, String> printer = new PrettyPrinter()::print;
     private static final Pattern JAVA_IDENTIFIER = Pattern.compile("\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*");
 
+    /**
+     * @param root the root directory of a set of source files. It corresponds to the root of the package structure of the
+     * source files within, like "javaparser/javaparser-core/src/main/java"
+     */
     public SourceRoot(Path root) {
         assertNotNull(root);
         if (!Files.isDirectory(root)) {
-            throw new IllegalArgumentException("Only directories are allowed as root path!");
+            throw new IllegalArgumentException("Only directories are allowed as root path: " + root);
         }
         this.root = root.normalize();
-        Log.info("New source root at \"%s\"", this.root);
-    }
-
-    public SourceRoot(Path root, ParserConfiguration parserConfiguration) {
-        this(root);
-        setParserConfiguration(parserConfiguration);
+        Log.info("New source root at \"%s\"", () -> this.root);
     }
 
     /**
-     * Tries to parse a .java files under the source root and returns the ParseResult. It keeps track of the parsed file
-     * so you can write it out with the saveAll() call. Note that the cache grows with every file parsed, so if you
-     * don't need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the cache is useful) you
-     * might want to use the parse method with a callback.
-     *
-     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
-     * @deprecated pass ParserConfiguration instead of JavaParser
+     * @param root the root directory of a set of source files. It corresponds to the root of the package structure of the
+     * source files within, like "javaparser/javaparser-core/src/main/java"
      */
-    @Deprecated
-    public ParseResult<CompilationUnit> tryToParse(String startPackage, String filename, JavaParser javaParser)
-            throws IOException {
-        return tryToParse(startPackage, filename, javaParser.getParserConfiguration());
+    public SourceRoot(Path root, ParserConfiguration parserConfiguration) {
+        this(root);
+        setParserConfiguration(parserConfiguration);
     }
 
     /**
@@ -104,14 +96,14 @@
         assertNotNull(filename);
         final Path relativePath = fileInPackageRelativePath(startPackage, filename);
         if (cache.containsKey(relativePath)) {
-            Log.trace("Retrieving cached %s", relativePath);
+            Log.trace("Retrieving cached %s", () -> relativePath);
             return cache.get(relativePath);
         }
         final Path path = root.resolve(relativePath);
-        Log.trace("Parsing %s", path);
+        Log.trace("Parsing %s", () -> path);
         final ParseResult<CompilationUnit> result = new JavaParser(configuration)
-                .parse(COMPILATION_UNIT, provider(path));
-        result.getResult().ifPresent(cu -> cu.setStorage(path));
+                .parse(COMPILATION_UNIT, provider(path, configuration.getCharacterEncoding()));
+        result.getResult().ifPresent(cu -> cu.setStorage(path, configuration.getCharacterEncoding()));
         cache.put(relativePath, result);
         return result;
     }
@@ -160,9 +152,11 @@
 
     private static boolean isSensibleDirectoryToEnter(Path dir) throws IOException {
         final String dirToEnter = dir.getFileName().toString();
+        // Don't enter directories that cannot be packages.
         final boolean directoryIsAValidJavaIdentifier = JAVA_IDENTIFIER.matcher(dirToEnter).matches();
+        // Don't enter directories that are hidden, assuming that people don't store source files in hidden directories.
         if (Files.isHidden(dir) || !directoryIsAValidJavaIdentifier) {
-            Log.trace("Not processing directory \"%s\"", dirToEnter);
+            Log.trace("Not processing directory \"%s\"", () -> dirToEnter);
             return false;
         }
         return true;
@@ -182,8 +176,9 @@
      * Tries to parse all .java files in a package recursively using multiple threads, and returns all files ever parsed
      * with this source root. A new thread is forked each time a new directory is visited and is responsible for parsing
      * all .java files in that directory. <b>Note that</b> to ensure thread safety, a new parser instance is created for
-     * every file with the internal parser's (i.e. {@link #setJavaParser}) configuration. It keeps track of all parsed
-     * files so you can write them out with a single saveAll() call. Note that the cache grows with every file parsed,
+     * every file with the internal parser's (i.e. {@link #setParserConfiguration(ParserConfiguration)}) configuration.
+     * It keeps track of all parsed files so you can write them out with a single saveAll() call.
+     * Note that the cache grows with every file parsed,
      * so if you don't need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the cache is
      * useful) you might want to use the parse method with a callback.
      *
@@ -216,12 +211,12 @@
      * Tries to parse all .java files under the source root recursively using multiple threads, and returns all files
      * ever parsed with this source root. A new thread is forked each time a new directory is visited and is responsible
      * for parsing all .java files in that directory. <b>Note that</b> to ensure thread safety, a new parser instance is
-     * created for every file with the internal parser's (i.e. {@link #setJavaParser}) configuration. It keeps track of
+     * created for every file with the internal (i.e. {@link #setParserConfiguration(ParserConfiguration)}) configuration. It keeps track of
      * all parsed files so you can write them out with a single saveAll() call. Note that the cache grows with every
      * file parsed, so if you don't need saveAll(), or you don't ask SourceRoot to parse files multiple times (where the
      * cache is useful) you might want to use the parse method with a callback.
      */
-    public List<ParseResult<CompilationUnit>> tryToParseParallelized() throws IOException {
+    public List<ParseResult<CompilationUnit>> tryToParseParallelized() {
         return tryToParseParallelized("");
     }
 
@@ -248,16 +243,47 @@
         }
     }
 
+    private FileVisitResult callback(Path absolutePath, ParserConfiguration configuration, Callback callback) throws IOException {
+        Path localPath = root.relativize(absolutePath);
+        Log.trace("Parsing %s", () -> localPath);
+        ParseResult<CompilationUnit> result = new JavaParser(configuration).parse(COMPILATION_UNIT, provider(absolutePath));
+        result.getResult().ifPresent(cu -> cu.setStorage(absolutePath, configuration.getCharacterEncoding()));
+        switch (callback.process(localPath, absolutePath, result)) {
+            case SAVE:
+                result.getResult().ifPresent(cu -> save(cu, absolutePath));
+            case DONT_SAVE:
+                return CONTINUE;
+            case TERMINATE:
+                return TERMINATE;
+            default:
+                throw new AssertionError("Return an enum defined in SourceRoot.Callback.Result");
+        }
+    }
+
     /**
-     * Tries to parse all .java files in a package recursively and passes them one by one to the callback. In comparison
-     * to the other parse methods, this is much more memory efficient, but saveAll() won't work.
+     * Locates the .java file with the provided package and file name, parses it and passes it to the
+     * callback. In comparison to the other parse methods, this is much more memory efficient, but saveAll() won't work.
      *
-     * @param startPackage files in this package and deeper are parsed. Pass "" to parse all files.
-     * @deprecated pass ParserConfiguration instead of JavaParser
+     * @param startPackage The package containing the file
+     * @param filename The name of the file
      */
-    @Deprecated
-    public SourceRoot parse(String startPackage, JavaParser javaParser, Callback callback) throws IOException {
-        return parse(startPackage, javaParser.getParserConfiguration(), callback);
+    public SourceRoot parse(String startPackage, String filename, ParserConfiguration configuration, Callback
+            callback) throws IOException {
+        assertNotNull(startPackage);
+        assertNotNull(filename);
+        assertNotNull(configuration);
+        assertNotNull(callback);
+        callback(fileInPackageAbsolutePath(root, startPackage, filename), configuration, callback);
+        return this;
+    }
+
+    /**
+     * Parses the provided .java file and passes it to the callback. In comparison to the other parse methods, this
+     * makes is much more memory efficient., but saveAll() won't work.
+     */
+    public SourceRoot parse(String startPackage, String filename, Callback callback) throws IOException {
+        parse(startPackage, filename, parserConfiguration, callback);
+        return this;
     }
 
     /**
@@ -271,31 +297,28 @@
         assertNotNull(configuration);
         assertNotNull(callback);
         logPackage(startPackage);
-        final JavaParser javaParser = new JavaParser(configuration);
         final Path path = packageAbsolutePath(root, startPackage);
-        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult visitFile(Path absolutePath, BasicFileAttributes attrs) throws IOException {
-                if (!attrs.isDirectory() && absolutePath.toString().endsWith(".java")) {
-                    Path localPath = root.relativize(absolutePath);
-                    Log.trace("Parsing %s", localPath);
-                    final ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT,
-                            provider(absolutePath));
-                    result.getResult().ifPresent(cu -> cu.setStorage(absolutePath));
-                    if (callback.process(localPath, absolutePath, result) == SAVE) {
-                        if (result.getResult().isPresent()) {
-                            save(result.getResult().get(), path);
-                        }
+        if (Files.exists(path)) {
+            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+                @Override
+                public FileVisitResult visitFile(Path absolutePath, BasicFileAttributes attrs) throws IOException {
+                    if (!attrs.isDirectory() && absolutePath.toString().endsWith(".java")) {
+                        return callback(absolutePath, configuration, callback);
                     }
+                    return CONTINUE;
                 }
-                return CONTINUE;
-            }
 
-            @Override
-            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
-                return isSensibleDirectoryToEnter(dir) ? CONTINUE : SKIP_SUBTREE;
-            }
-        });
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+                    return isSensibleDirectoryToEnter(dir) ? CONTINUE : SKIP_SUBTREE;
+                }
+            });
+        }
+        return this;
+    }
+
+    public SourceRoot parse(String startPackage, Callback callback) throws IOException {
+        parse(startPackage, parserConfiguration, callback);
         return this;
     }
 
@@ -303,7 +326,7 @@
         if (startPackage.isEmpty()) {
             return;
         }
-        Log.info("Parsing package \"%s\"", startPackage);
+        Log.info("Parsing package \"%s\"", () -> startPackage);
     }
 
     /**
@@ -322,27 +345,20 @@
         assertNotNull(callback);
         logPackage(startPackage);
         final Path path = packageAbsolutePath(root, startPackage);
-        ParallelParse parse = new ParallelParse(path, (file, attrs) -> {
-            if (!attrs.isDirectory() && file.toString().endsWith(".java")) {
-                Path localPath = root.relativize(file);
-                Log.trace("Parsing %s", localPath);
-                try {
-                    ParseResult<CompilationUnit> result = new JavaParser(configuration)
-                            .parse(COMPILATION_UNIT, provider(file));
-                    result.getResult().ifPresent(cu -> cu.setStorage(file));
-                    if (callback.process(localPath, file, result) == SAVE) {
-                        if (result.getResult().isPresent()) {
-                            save(result.getResult().get(), path);
-                        }
+        if (Files.exists(path)) {
+            ParallelParse parse = new ParallelParse(path, (absolutePath, attrs) -> {
+                if (!attrs.isDirectory() && absolutePath.toString().endsWith(".java")) {
+                    try {
+                        return callback(absolutePath, configuration, callback);
+                    } catch (IOException e) {
+                        Log.error(e);
                     }
-                } catch (IOException e) {
-                    Log.error(e);
                 }
-            }
-            return CONTINUE;
-        });
-        ForkJoinPool pool = new ForkJoinPool();
-        pool.invoke(parse);
+                return CONTINUE;
+            });
+            ForkJoinPool pool = new ForkJoinPool();
+            pool.invoke(parse);
+        }
         return this;
     }
 
@@ -379,12 +395,11 @@
         assertNotNull(startPackage);
         assertNotNull(filename);
         assertNotNull(compilationUnit);
-        Log.trace("Adding new file %s.%s", startPackage, filename);
+        Log.trace("Adding new file %s.%s", () -> startPackage, () -> filename);
         final Path path = fileInPackageRelativePath(startPackage, filename);
         final ParseResult<CompilationUnit> parseResult = new ParseResult<>(
                 compilationUnit,
                 new ArrayList<>(),
-                null,
                 null);
         cache.put(path, parseResult);
         return this;
@@ -398,11 +413,10 @@
         assertNotNull(compilationUnit);
         if (compilationUnit.getStorage().isPresent()) {
             final Path path = compilationUnit.getStorage().get().getPath();
-            Log.trace("Adding new file %s", path);
+            Log.trace("Adding new file %s", () -> path);
             final ParseResult<CompilationUnit> parseResult = new ParseResult<>(
                     compilationUnit,
                     new ArrayList<>(),
-                    null,
                     null);
             cache.put(path, parseResult);
         } else {
@@ -413,32 +427,54 @@
 
     /**
      * Save the given compilation unit to the given path.
+     * @param cu the compilation unit
+     * @param path the path of the java file
      */
     private SourceRoot save(CompilationUnit cu, Path path) {
+        return save(cu, path, parserConfiguration.getCharacterEncoding());
+    }
+
+    /**
+     * Save the given compilation unit to the given path.
+     * @param cu the compilation unit
+     * @param path the path of the java file
+     * @param encoding  the encoding to use while saving the file
+     */
+    private SourceRoot save(CompilationUnit cu, Path path, Charset encoding) {
         assertNotNull(cu);
         assertNotNull(path);
-        cu.setStorage(path);
+        cu.setStorage(path, encoding);
         cu.getStorage().get().save(printer);
         return this;
     }
 
     /**
      * Save all previously parsed files back to a new path.
+     * @param root the root of the java packages
+     * @param encoding the encoding to use while saving the file
      */
-    public SourceRoot saveAll(Path root) {
+    public SourceRoot saveAll(Path root, Charset encoding) {
         assertNotNull(root);
-        Log.info("Saving all files (%s) to %s", cache.size(), root);
+        Log.info("Saving all files (%s) to %s", cache::size, () -> root);
         for (Map.Entry<Path, ParseResult<CompilationUnit>> cu : cache.entrySet()) {
             final Path path = root.resolve(cu.getKey());
             if (cu.getValue().getResult().isPresent()) {
-                Log.trace("Saving %s", path);
-                save(cu.getValue().getResult().get(), path);
+                Log.trace("Saving %s", () -> path);
+                save(cu.getValue().getResult().get(), path, encoding);
             }
         }
         return this;
     }
 
     /**
+     * Save all previously parsed files back to a new path.
+     * @param root the root of the java packages
+     */
+    public SourceRoot saveAll(Path root) {
+        return saveAll(root, parserConfiguration.getCharacterEncoding());
+    }
+
+    /**
      * Save all previously parsed files back to where they were found.
      */
     public SourceRoot saveAll() {
@@ -446,6 +482,14 @@
     }
 
     /**
+     * Save all previously parsed files back to where they were found, with the given encoding.
+     * @param encoding the encoding to use.
+     */
+    public SourceRoot saveAll(Charset encoding) {
+        return saveAll(root, encoding);
+    }
+
+    /**
      * The Java files that have been parsed by this source root object, or have been added manually.
      */
     public List<ParseResult<CompilationUnit>> getCache() {
@@ -470,26 +514,6 @@
         return root;
     }
 
-    /**
-     * @deprecated store ParserConfiguration now
-     */
-    @Deprecated
-    public JavaParser getJavaParser() {
-        return new JavaParser(parserConfiguration);
-    }
-
-    /**
-     * Set the parser that is used for parsing by default.
-     *
-     * @deprecated store ParserConfiguration now
-     */
-    @Deprecated
-    public SourceRoot setJavaParser(JavaParser javaParser) {
-        assertNotNull(javaParser);
-        this.parserConfiguration = javaParser.getParserConfiguration();
-        return this;
-    }
-
     public ParserConfiguration getParserConfiguration() {
         return parserConfiguration;
     }
@@ -574,4 +598,9 @@
             FileVisitResult process(Path file, BasicFileAttributes attrs);
         }
     }
+
+    @Override
+    public String toString() {
+        return "SourceRoot at " + root;
+    }
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/SourceZip.java b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceZip.java
index ffb64f4..b31a2ab 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/SourceZip.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/SourceZip.java
@@ -1,169 +1,149 @@
-/*

- * 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.utils;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ParseResult;

-import com.github.javaparser.ParserConfiguration;

-import com.github.javaparser.ast.CompilationUnit;

-

-import java.io.IOException;

-import java.nio.file.Path;

-import java.nio.file.Paths;

-import java.util.ArrayList;

-import java.util.Collections;

-import java.util.List;

-import java.util.zip.ZipEntry;

-import java.util.zip.ZipFile;

-

-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;

-import static com.github.javaparser.Providers.provider;

-import static com.github.javaparser.utils.Utils.assertNotNull;

-

-/**

- * A collection of Java source files and its sub-directories located in a ZIP or JAR file on the file system.

- * Files can be parsed with a callback.

- *

- */

-public class SourceZip {

-

-    private final Path zipPath;

-    private ParserConfiguration parserConfiguration;

-

-    /**

-     * Create a new ZIP parser. An instance of {@link JavaParser} with the default {@link ParserConfiguration} will be

-     * used to parse the ZIP.

-     *

-     * @param zipPath The absolute path of ZIP file to parse.

-     */

-    public SourceZip(Path zipPath) {

-        this(zipPath, new ParserConfiguration());

-    }

-

-    /**

-     * Create a new ZIP parser. An instance of {@link JavaParser} with the given configuration will be used to parse

-     * the ZIP.

-     *

-     * @param zipPath The absolute path of ZIP file to parse.

-     * @param configuration The configuration to initiate the default parser with.

-     */

-    public SourceZip(Path zipPath, ParserConfiguration configuration) {

-        assertNotNull(zipPath);

-        assertNotNull(configuration);

-        this.zipPath = zipPath.normalize();

-        this.parserConfiguration = configuration;

-        Log.info("New source zip at \"%s\"", this.zipPath);

-    }

-

-    /**

-     * Tries to parse all '.java' files in the ZIP located at this <i>SourceZip</i>'s path and returns the parse

-     * results in a list.

-     *

-     * @return A list of path-compilation unit pairs.

-     *

-     * @throws IOException If an error occurs while trying to parse the given source.

-     */

-    public List<Pair<Path, ParseResult<CompilationUnit>>> parse() throws IOException {

-        Log.info("Parsing zip at \"%s\"", zipPath);

-        List<Pair<Path, ParseResult<CompilationUnit>>> results = new ArrayList<>();

-        parse((path, result) -> results.add(new Pair<>(path, result)));

-        return results;

-    }

-

-    /**

-     * Tries to parse all '.java' files in the ZIP located at this <i>SourceZip</i>'s path and returns the parse

-     * results in a list.

-     *

-     * @return A list of path-compilation unit pairs.

-     *

-     * @throws IOException If an error occurs while trying to parse the given source.

-     */

-    public SourceZip parse(Callback callback) throws IOException {

-        Log.info("Parsing zip at \"%s\"", zipPath);

-        JavaParser javaParser = new JavaParser(parserConfiguration);

-        try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {

-            for (ZipEntry entry : Collections.list(zipFile.entries())) {

-                if (!entry.isDirectory() && entry.getName().endsWith(".java")) {

-                    Log.info("Parsing zip entry \"%s\"", entry.getName());

-                    final ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT,

-                            provider(zipFile.getInputStream(entry)));

-                    callback.process(Paths.get(entry.getName()), result);

-                }

-            }

-        }

-        return this;

-    }

-

-    /**

-     * An interface to define a callback for each file that's parsed.

-     */

-    @FunctionalInterface

-    public interface Callback {

-

-        /**

-         * Process the given parse result.

-         *

-         * @param relativeZipEntryPath The relative path of the entry in the ZIP file that was parsed.

-         * @param result The parse result of file located at <i>absolutePath</i>.

-         */

-        void process(Path relativeZipEntryPath, ParseResult<CompilationUnit> result);

-    }

-

-    /**

-     * Get the path of the ZIP file to be parsed.

-     *

-     * @return The absolute path of this ZIP file.

-     */

-    public Path getZipPath() {

-        return zipPath;

-    }

-    

-    /**

-     * @deprecated store ParserConfiguration now

-     */

-    @Deprecated

-    public JavaParser getJavaParser() {

-        return new JavaParser(parserConfiguration);

-    }

-

-    /**

-     * Set the parser that is used for parsing by default.

-     *

-     * @deprecated store ParserConfiguration now

-     */

-    @Deprecated

-    public SourceZip setJavaParser(JavaParser javaParser) {

-        assertNotNull(javaParser);

-        this.parserConfiguration = javaParser.getParserConfiguration();

-        return this;

-    }

-

-    public ParserConfiguration getParserConfiguration() {

-        return parserConfiguration;

-    }

-

-    public SourceZip setParserConfiguration(ParserConfiguration parserConfiguration) {

-        assertNotNull(parserConfiguration);

-        this.parserConfiguration = parserConfiguration;

-        return this;

-    }

-}

+/*
+ * 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.utils;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.CompilationUnit;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+import static com.github.javaparser.Providers.provider;
+import static com.github.javaparser.utils.Utils.assertNotNull;
+
+/**
+ * A collection of Java source files and its sub-directories located in a ZIP or JAR file on the file system.
+ * Files can be parsed with a callback.
+ *
+ */
+public class SourceZip {
+
+    private final Path zipPath;
+    private ParserConfiguration parserConfiguration;
+
+    /**
+     * Create a new ZIP parser. An instance of {@link JavaParser} with the default {@link ParserConfiguration} will be
+     * used to parse the ZIP.
+     *
+     * @param zipPath The absolute path of ZIP file to parse.
+     */
+    public SourceZip(Path zipPath) {
+        this(zipPath, new ParserConfiguration());
+    }
+
+    /**
+     * Create a new ZIP parser. An instance of {@link JavaParser} with the given configuration will be used to parse
+     * the ZIP.
+     *
+     * @param zipPath The absolute path of ZIP file to parse.
+     * @param configuration The configuration to initiate the default parser with.
+     */
+    public SourceZip(Path zipPath, ParserConfiguration configuration) {
+        assertNotNull(zipPath);
+        assertNotNull(configuration);
+        this.zipPath = zipPath.normalize();
+        this.parserConfiguration = configuration;
+        Log.info("New source zip at \"%s\"", ()->this.zipPath);
+    }
+
+    /**
+     * Tries to parse all '.java' files in the ZIP located at this <i>SourceZip</i>'s path and returns the parse
+     * results in a list.
+     *
+     * @return A list of path-compilation unit pairs.
+     *
+     * @throws IOException If an error occurs while trying to parse the given source.
+     */
+    public List<Pair<Path, ParseResult<CompilationUnit>>> parse() throws IOException {
+        Log.info("Parsing zip at \"%s\"", ()-> zipPath);
+        List<Pair<Path, ParseResult<CompilationUnit>>> results = new ArrayList<>();
+        parse((path, result) -> results.add(new Pair<>(path, result)));
+        return results;
+    }
+
+    /**
+     * Tries to parse all '.java' files in the ZIP located at this <i>SourceZip</i>'s path and returns the parse
+     * results in a list.
+     *
+     * @return A list of path-compilation unit pairs.
+     *
+     * @throws IOException If an error occurs while trying to parse the given source.
+     */
+    public SourceZip parse(Callback callback) throws IOException {
+        Log.info("Parsing zip at \"%s\"", ()-> zipPath);
+        JavaParser javaParser = new JavaParser(parserConfiguration);
+        try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {
+            for (ZipEntry entry : Collections.list(zipFile.entries())) {
+                if (!entry.isDirectory() && entry.getName().endsWith(".java")) {
+                    Log.info("Parsing zip entry \"%s\"", ()-> entry.getName());
+                    final ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT,
+                            provider(zipFile.getInputStream(entry)));
+                    callback.process(Paths.get(entry.getName()), result);
+                }
+            }
+        }
+        return this;
+    }
+
+    /**
+     * An interface to define a callback for each file that's parsed.
+     */
+    @FunctionalInterface
+    public interface Callback {
+
+        /**
+         * Process the given parse result.
+         *
+         * @param relativeZipEntryPath The relative path of the entry in the ZIP file that was parsed.
+         * @param result The parse result of file located at <i>absolutePath</i>.
+         */
+        void process(Path relativeZipEntryPath, ParseResult<CompilationUnit> result);
+    }
+
+    /**
+     * Get the path of the ZIP file to be parsed.
+     *
+     * @return The absolute path of this ZIP file.
+     */
+    public Path getZipPath() {
+        return zipPath;
+    }
+    
+    public ParserConfiguration getParserConfiguration() {
+        return parserConfiguration;
+    }
+
+    public SourceZip setParserConfiguration(ParserConfiguration parserConfiguration) {
+        assertNotNull(parserConfiguration);
+        this.parserConfiguration = parserConfiguration;
+        return this;
+    }
+}
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/Utils.java b/javaparser-core/src/main/java/com/github/javaparser/utils/Utils.java
index 2db00e5..9ffed19 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/Utils.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/Utils.java
@@ -23,6 +23,7 @@
 
 import java.io.IOException;
 import java.io.Reader;
+import java.nio.file.Files;
 import java.util.*;
 import java.util.function.Predicate;
 import java.util.function.Function;
@@ -37,15 +38,6 @@
 public class Utils {
     public static final String EOL = System.getProperty("line.separator");
 
-    public static final Predicate<String> STRING_NOT_EMPTY = s -> !s.isEmpty();
-
-    /**
-     * @deprecated This is no longer in use by JavaParser, please write your own replacement.
-     */
-    public static <T> List<T> ensureNotNull(List<T> list) {
-        return list == null ? new ArrayList<>() : list;
-    }
-
     public static <E> boolean isNullOrEmpty(Collection<E> collection) {
         return collection == null || collection.isEmpty();
     }
@@ -64,6 +56,20 @@
         return string;
     }
 
+    public static <T extends Number> T assertNonNegative(T number) {
+        if (number.longValue() < 0) {
+            throw new AssertionError("A number was unexpectedly negative.");
+        }
+        return number;
+    }
+
+    public static <T extends Number> T assertPositive(T number) {
+        if (number.longValue() <= 0) {
+            throw new AssertionError("A number was unexpectedly non-positive.");
+        }
+        return number;
+    }
+
     /**
      * @return string with ASCII characters 10 and 13 replaced by the text "\n" and "\r".
      */
@@ -97,19 +103,6 @@
     }
 
     /**
-     * Puts varargs in a mutable list.
-     * This does not have the disadvantage of Arrays#asList that it has a static size.
-     *
-     * @deprecated This is no longer in use by JavaParser, please write your own replacement.
-     */
-    @Deprecated
-    public static <T> List<T> arrayToList(T[] array) {
-        List<T> list = new LinkedList<>();
-        Collections.addAll(list, array);
-        return list;
-    }
-
-    /**
      * @deprecated use screamingToCamelCase
      */
     public static String toCamelCase(String original) {
@@ -214,6 +207,55 @@
         return false;
     }
 
+    public static boolean valueIsNullOrEmptyStringOrOptional(Object value) {
+        if (value == null) {
+            return true;
+        }
+        if (value instanceof Optional) {
+            if (((Optional) value).isPresent()) {
+                value = ((Optional) value).get();
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Like {@link List#set(int, Object)} at {@link List#indexOf(Object)}, but using ==, not equals.
+     */
+    public static <E> void replaceElementByObjectIdentity(List<E> list, E oldObject, E newObject) {
+        int index = indexOfElementByObjectIdentity(list, oldObject);
+        if (index == -1) {
+            return;
+        }
+        list.set(index, newObject);
+    }
+
+    /**
+     * Like {@link List#remove(Object)}, but using ==, not equals.
+     */
+    public static <E> void removeElementByObjectIdentity(List<E> list, E o) {
+        int index = indexOfElementByObjectIdentity(list, o);
+        if (index == -1) {
+            return;
+        }
+        list.remove(index);
+    }
+
+    /**
+     * Like {@link List#indexOf(Object)}, but using ==, not equals.
+     */
+    public static <E> int indexOfElementByObjectIdentity(List<E> list, E o) {
+        for (int i = 0; i < list.size(); i++) {
+            Object listO = list.get(i);
+            if (o == listO) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     /**
      * @return a set of the items.
      */
diff --git a/javaparser-core/src/main/java/com/github/javaparser/version/Java11PostProcessor.java b/javaparser-core/src/main/java/com/github/javaparser/version/Java11PostProcessor.java
index 004967e..63095ab 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/version/Java11PostProcessor.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/version/Java11PostProcessor.java
@@ -1,7 +1,7 @@
 package com.github.javaparser.version;
 
 /**
- * Processes the generic AST into a Java 10 AST and validates it.
+ * Processes the generic AST into a Java 11 AST and validates it.
  */
 public class Java11PostProcessor extends Java10PostProcessor {
 }
diff --git a/javaparser-core/src/main/java/com/github/javaparser/version/Java12PostProcessor.java b/javaparser-core/src/main/java/com/github/javaparser/version/Java12PostProcessor.java
new file mode 100644
index 0000000..78b03b2
--- /dev/null
+++ b/javaparser-core/src/main/java/com/github/javaparser/version/Java12PostProcessor.java
@@ -0,0 +1,7 @@
+package com.github.javaparser.version;
+
+/**
+ * Processes the generic AST into a Java 12 AST and validates it.
+ */
+public class Java12PostProcessor extends Java11PostProcessor {
+}
diff --git a/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserBase.java b/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserBase.java
index ef0b7ef..5a44172 100644
--- a/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserBase.java
+++ b/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserBase.java
@@ -1,7 +1,6 @@
 package com.github.javaparser;
 
 import com.github.javaparser.ast.ArrayCreationLevel;
-import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.body.Parameter;
@@ -236,16 +235,6 @@
     }
 
     /**
-     * Add modifier mod to modifiers
-     */
-    void addModifier(EnumSet<Modifier> modifiers, Modifier mod) {
-        if (modifiers.contains(mod)) {
-            addProblem("Duplicated modifier");
-        }
-        modifiers.add(mod);
-    }
-
-    /**
      * Propagate expansion of the range on the right to the parent. This is necessary when the right border of the child
      * is determining the right border of the parent (i.e., the child is the last element of the parent). In this case
      * when we "enlarge" the child we should enlarge also the parent.
@@ -269,11 +258,11 @@
         if (ret instanceof EnclosedExpr) {
             Expression inner = ((EnclosedExpr) ret).getInner();
             SimpleName id = ((NameExpr) inner).getName();
-            NodeList<Parameter> params = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), EnumSet.noneOf(Modifier.class), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
+            NodeList<Parameter> params = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), new NodeList<>(), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
             ret = new LambdaExpr(range(ret, lambdaBody), params, lambdaBody, true);
         } else if (ret instanceof NameExpr) {
             SimpleName id = ((NameExpr) ret).getName();
-            NodeList<Parameter> params = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), EnumSet.noneOf(Modifier.class), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
+            NodeList<Parameter> params = add(new NodeList<>(), new Parameter(ret.getTokenRange().orElse(null), new NodeList<>(), new NodeList<>(), new UnknownType(), false, new NodeList<>(), id));
             ret = new LambdaExpr(range(ret, lambdaBody), params, lambdaBody, false);
         } else if (ret instanceof LambdaExpr) {
             ((LambdaExpr) ret).setBody(lambdaBody);
@@ -332,8 +321,6 @@
             expected.append(" ").append(option);
         }
 
-        sb.append("");
-
         Token token = exception.currentToken.next;
         for (int i = 0; i < maxExpectedTokenSequenceLength; i++) {
             String tokenText = token.image;
@@ -366,4 +353,20 @@
         }
         return sb.toString();
     }
+
+    /**
+     * Converts a NameExpr or a FieldAccessExpr scope to a Name. 
+     */
+    Name scopeToName(Expression scope) {
+        if (scope.isNameExpr()) {
+            SimpleName simpleName = scope.asNameExpr().getName();
+            return new Name(simpleName.getTokenRange().get(), null, simpleName.getIdentifier());
+        }
+        if (scope.isFieldAccessExpr()) {
+            FieldAccessExpr fieldAccessExpr = scope.asFieldAccessExpr();
+            return new Name(fieldAccessExpr.getTokenRange().get(), scopeToName(fieldAccessExpr.getScope()), fieldAccessExpr.getName().getIdentifier());
+
+        }
+        throw new IllegalStateException("Unexpected expression type: " + scope.getClass().getSimpleName());
+    }
 }
diff --git a/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserTokenManagerBase.java b/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserTokenManagerBase.java
index da4331e..4a79019 100644
--- a/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserTokenManagerBase.java
+++ b/javaparser-core/src/main/javacc-support/com/github/javaparser/GeneratedJavaParserTokenManagerBase.java
@@ -6,7 +6,6 @@
 import com.github.javaparser.ast.comments.LineComment;
 
 import static com.github.javaparser.GeneratedJavaParserConstants.*;
-import static com.github.javaparser.Position.pos;
 
 /**
  * Base class for {@link com.github.javaparser.GeneratedJavaParserTokenManager}
@@ -31,15 +30,7 @@
         } else if (token.kind == MULTI_LINE_COMMENT) {
             return new BlockComment(tokenRange(token), commentText.substring(2, commentText.length() - 2));
         } else if (token.kind == SINGLE_LINE_COMMENT) {
-            // line comments have their end of line character(s) included, and we don't want that.
-            Range range = new Range(pos(token.beginLine, token.beginColumn), pos(token.endLine, token.endColumn));
-            while (commentText.endsWith("\r") || commentText.endsWith("\n")) {
-                commentText = commentText.substring(0, commentText.length() - 1);
-            }
-            range = range.withEnd(pos(range.begin.line, range.begin.column + commentText.length()));
-            LineComment comment = new LineComment(tokenRange(token), commentText.substring(2));
-            comment.setRange(range);
-            return comment;
+            return new LineComment(tokenRange(token), commentText.substring(2));
         }
         throw new AssertionError("Unexpectedly got passed a non-comment token.");
     }
diff --git a/javaparser-core/src/main/javacc-support/com/github/javaparser/ModifierHolder.java b/javaparser-core/src/main/javacc-support/com/github/javaparser/ModifierHolder.java
index 46d2e8f..2c10f7e 100644
--- a/javaparser-core/src/main/javacc-support/com/github/javaparser/ModifierHolder.java
+++ b/javaparser-core/src/main/javacc-support/com/github/javaparser/ModifierHolder.java
@@ -4,19 +4,17 @@
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.expr.AnnotationExpr;
 
-import java.util.EnumSet;
-
 import static com.github.javaparser.utils.Utils.assertNotNull;
 
 /**
  * Helper class for {@link GeneratedJavaParser}
  */
 class ModifierHolder {
-    final EnumSet<Modifier> modifiers;
+    final NodeList<Modifier> modifiers;
     final NodeList<AnnotationExpr> annotations;
     final JavaToken begin;
 
-    ModifierHolder(JavaToken begin, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations) {
+    ModifierHolder(JavaToken begin, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations) {
         this.begin = begin;
         this.modifiers = assertNotNull(modifiers);
         this.annotations = annotations;
diff --git a/javaparser-core/src/main/javacc/java.jj b/javaparser-core/src/main/javacc/java.jj
index c688228..6bce177 100644
--- a/javaparser-core/src/main/javacc/java.jj
+++ b/javaparser-core/src/main/javacc/java.jj
@@ -59,7 +59,6 @@
 import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.ast.type.*;
 import com.github.javaparser.utils.*;
-import javax.annotation.Generated;
 import static com.github.javaparser.JavaToken.INVALID;
 import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
 import static com.github.javaparser.utils.Utils.*;
@@ -69,6 +68,7 @@
 import static com.github.javaparser.Position.*;
 import static com.github.javaparser.ast.type.ArrayType.*;
 import static com.github.javaparser.GeneratedJavaParserTokenManagerBase.*;
+import static com.github.javaparser.ast.stmt.SwitchEntry.Type.*;
 
 @Generated("JavaCC")
 final class GeneratedJavaParser extends GeneratedJavaParserBase {
@@ -169,7 +169,7 @@
 
 SPECIAL_TOKEN :
 {
-  <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
+  <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])*>
 }
 
 MORE :
@@ -365,155 +365,159 @@
   < #LETTER: [
          "\u0024",  "\u0041"-"\u005a",  "\u005f",  "\u0061"-"\u007a",  "\u00a2"-"\u00a5",  "\u00aa",  "\u00b5",  
          "\u00ba",  "\u00c0"-"\u00d6",  "\u00d8"-"\u00f6",  "\u00f8"-"\u02c1",  "\u02c6"-"\u02d1",  "\u02e0"-"\u02e4",  
-         "\u02ec",  "\u02ee",  "\u0370"-"\u0374",  "\u0376"-"\u0377",  "\u037a"-"\u037d",  "\u0386",  "\u0388"-"\u038a",  
-         "\u038c",  "\u038e"-"\u03a1",  "\u03a3"-"\u03f5",  "\u03f7"-"\u0481",  "\u048a"-"\u0527",  "\u0531"-"\u0556",  
-         "\u0559",  "\u0561"-"\u0587",  "\u058f",  "\u05d0"-"\u05ea",  "\u05f0"-"\u05f2",  "\u060b",  "\u0620"-"\u064a",  
-         "\u066e"-"\u066f",  "\u0671"-"\u06d3",  "\u06d5",  "\u06e5"-"\u06e6",  "\u06ee"-"\u06ef",  "\u06fa"-"\u06fc",  
-         "\u06ff",  "\u0710",  "\u0712"-"\u072f",  "\u074d"-"\u07a5",  "\u07b1",  "\u07ca"-"\u07ea",  "\u07f4"-"\u07f5",  
-         "\u07fa",  "\u0800"-"\u0815",  "\u081a",  "\u0824",  "\u0828",  "\u0840"-"\u0858",  "\u08a0",  "\u08a2"-"\u08ac",  
-         "\u0904"-"\u0939",  "\u093d",  "\u0950",  "\u0958"-"\u0961",  "\u0971"-"\u0977",  "\u0979"-"\u097f",  
-         "\u0985"-"\u098c",  "\u098f"-"\u0990",  "\u0993"-"\u09a8",  "\u09aa"-"\u09b0",  "\u09b2",  "\u09b6"-"\u09b9",  
-         "\u09bd",  "\u09ce",  "\u09dc"-"\u09dd",  "\u09df"-"\u09e1",  "\u09f0"-"\u09f3",  "\u09fb",  "\u0a05"-"\u0a0a",  
-         "\u0a0f"-"\u0a10",  "\u0a13"-"\u0a28",  "\u0a2a"-"\u0a30",  "\u0a32"-"\u0a33",  "\u0a35"-"\u0a36",  
-         "\u0a38"-"\u0a39",  "\u0a59"-"\u0a5c",  "\u0a5e",  "\u0a72"-"\u0a74",  "\u0a85"-"\u0a8d",  "\u0a8f"-"\u0a91",  
-         "\u0a93"-"\u0aa8",  "\u0aaa"-"\u0ab0",  "\u0ab2"-"\u0ab3",  "\u0ab5"-"\u0ab9",  "\u0abd",  "\u0ad0",  
-         "\u0ae0"-"\u0ae1",  "\u0af1",  "\u0b05"-"\u0b0c",  "\u0b0f"-"\u0b10",  "\u0b13"-"\u0b28",  "\u0b2a"-"\u0b30",  
-         "\u0b32"-"\u0b33",  "\u0b35"-"\u0b39",  "\u0b3d",  "\u0b5c"-"\u0b5d",  "\u0b5f"-"\u0b61",  "\u0b71",  
-         "\u0b83",  "\u0b85"-"\u0b8a",  "\u0b8e"-"\u0b90",  "\u0b92"-"\u0b95",  "\u0b99"-"\u0b9a",  "\u0b9c",  
-         "\u0b9e"-"\u0b9f",  "\u0ba3"-"\u0ba4",  "\u0ba8"-"\u0baa",  "\u0bae"-"\u0bb9",  "\u0bd0",  "\u0bf9",  
-         "\u0c05"-"\u0c0c",  "\u0c0e"-"\u0c10",  "\u0c12"-"\u0c28",  "\u0c2a"-"\u0c33",  "\u0c35"-"\u0c39",  
-         "\u0c3d",  "\u0c58"-"\u0c59",  "\u0c60"-"\u0c61",  "\u0c85"-"\u0c8c",  "\u0c8e"-"\u0c90",  "\u0c92"-"\u0ca8",  
-         "\u0caa"-"\u0cb3",  "\u0cb5"-"\u0cb9",  "\u0cbd",  "\u0cde",  "\u0ce0"-"\u0ce1",  "\u0cf1"-"\u0cf2",  
-         "\u0d05"-"\u0d0c",  "\u0d0e"-"\u0d10",  "\u0d12"-"\u0d3a",  "\u0d3d",  "\u0d4e",  "\u0d60"-"\u0d61",  
-         "\u0d7a"-"\u0d7f",  "\u0d85"-"\u0d96",  "\u0d9a"-"\u0db1",  "\u0db3"-"\u0dbb",  "\u0dbd",  "\u0dc0"-"\u0dc6",  
-         "\u0e01"-"\u0e30",  "\u0e32"-"\u0e33",  "\u0e3f"-"\u0e46",  "\u0e81"-"\u0e82",  "\u0e84",  "\u0e87"-"\u0e88",  
-         "\u0e8a",  "\u0e8d",  "\u0e94"-"\u0e97",  "\u0e99"-"\u0e9f",  "\u0ea1"-"\u0ea3",  "\u0ea5",  "\u0ea7",  
-         "\u0eaa"-"\u0eab",  "\u0ead"-"\u0eb0",  "\u0eb2"-"\u0eb3",  "\u0ebd",  "\u0ec0"-"\u0ec4",  "\u0ec6",  
-         "\u0edc"-"\u0edf",  "\u0f00",  "\u0f40"-"\u0f47",  "\u0f49"-"\u0f6c",  "\u0f88"-"\u0f8c",  "\u1000"-"\u102a",  
-         "\u103f",  "\u1050"-"\u1055",  "\u105a"-"\u105d",  "\u1061",  "\u1065"-"\u1066",  "\u106e"-"\u1070",  
-         "\u1075"-"\u1081",  "\u108e",  "\u10a0"-"\u10c5",  "\u10c7",  "\u10cd",  "\u10d0"-"\u10fa",  "\u10fc"-"\u1248",  
-         "\u124a"-"\u124d",  "\u1250"-"\u1256",  "\u1258",  "\u125a"-"\u125d",  "\u1260"-"\u1288",  "\u128a"-"\u128d",  
-         "\u1290"-"\u12b0",  "\u12b2"-"\u12b5",  "\u12b8"-"\u12be",  "\u12c0",  "\u12c2"-"\u12c5",  "\u12c8"-"\u12d6",  
-         "\u12d8"-"\u1310",  "\u1312"-"\u1315",  "\u1318"-"\u135a",  "\u1380"-"\u138f",  "\u13a0"-"\u13f4",  
-         "\u1401"-"\u166c",  "\u166f"-"\u167f",  "\u1681"-"\u169a",  "\u16a0"-"\u16ea",  "\u16ee"-"\u16f0",  
-         "\u1700"-"\u170c",  "\u170e"-"\u1711",  "\u1720"-"\u1731",  "\u1740"-"\u1751",  "\u1760"-"\u176c",  
-         "\u176e"-"\u1770",  "\u1780"-"\u17b3",  "\u17d7",  "\u17db"-"\u17dc",  "\u1820"-"\u1877",  "\u1880"-"\u18a8",  
-         "\u18aa",  "\u18b0"-"\u18f5",  "\u1900"-"\u191c",  "\u1950"-"\u196d",  "\u1970"-"\u1974",  "\u1980"-"\u19ab",  
-         "\u19c1"-"\u19c7",  "\u1a00"-"\u1a16",  "\u1a20"-"\u1a54",  "\u1aa7",  "\u1b05"-"\u1b33",  "\u1b45"-"\u1b4b",  
-         "\u1b83"-"\u1ba0",  "\u1bae"-"\u1baf",  "\u1bba"-"\u1be5",  "\u1c00"-"\u1c23",  "\u1c4d"-"\u1c4f",  
-         "\u1c5a"-"\u1c7d",  "\u1ce9"-"\u1cec",  "\u1cee"-"\u1cf1",  "\u1cf5"-"\u1cf6",  "\u1d00"-"\u1dbf",  
-         "\u1e00"-"\u1f15",  "\u1f18"-"\u1f1d",  "\u1f20"-"\u1f45",  "\u1f48"-"\u1f4d",  "\u1f50"-"\u1f57",  
-         "\u1f59",  "\u1f5b",  "\u1f5d",  "\u1f5f"-"\u1f7d",  "\u1f80"-"\u1fb4",  "\u1fb6"-"\u1fbc",  "\u1fbe",  
-         "\u1fc2"-"\u1fc4",  "\u1fc6"-"\u1fcc",  "\u1fd0"-"\u1fd3",  "\u1fd6"-"\u1fdb",  "\u1fe0"-"\u1fec",  
-         "\u1ff2"-"\u1ff4",  "\u1ff6"-"\u1ffc",  "\u203f"-"\u2040",  "\u2054",  "\u2071",  "\u207f",  "\u2090"-"\u209c",  
-         "\u20a0"-"\u20ba",  "\u2102",  "\u2107",  "\u210a"-"\u2113",  "\u2115",  "\u2119"-"\u211d",  "\u2124",  
-         "\u2126",  "\u2128",  "\u212a"-"\u212d",  "\u212f"-"\u2139",  "\u213c"-"\u213f",  "\u2145"-"\u2149",  
-         "\u214e",  "\u2160"-"\u2188",  "\u2c00"-"\u2c2e",  "\u2c30"-"\u2c5e",  "\u2c60"-"\u2ce4",  "\u2ceb"-"\u2cee",  
-         "\u2cf2"-"\u2cf3",  "\u2d00"-"\u2d25",  "\u2d27",  "\u2d2d",  "\u2d30"-"\u2d67",  "\u2d6f",  "\u2d80"-"\u2d96",  
-         "\u2da0"-"\u2da6",  "\u2da8"-"\u2dae",  "\u2db0"-"\u2db6",  "\u2db8"-"\u2dbe",  "\u2dc0"-"\u2dc6",  
-         "\u2dc8"-"\u2dce",  "\u2dd0"-"\u2dd6",  "\u2dd8"-"\u2dde",  "\u2e2f",  "\u3005"-"\u3007",  "\u3021"-"\u3029",  
-         "\u3031"-"\u3035",  "\u3038"-"\u303c",  "\u3041"-"\u3096",  "\u309d"-"\u309f",  "\u30a1"-"\u30fa",  
-         "\u30fc"-"\u30ff",  "\u3105"-"\u312d",  "\u3131"-"\u318e",  "\u31a0"-"\u31ba",  "\u31f0"-"\u31ff",  
-         "\u3400"-"\u4db5",  "\u4e00"-"\u9fcc",  "\ua000"-"\ua48c",  "\ua4d0"-"\ua4fd",  "\ua500"-"\ua60c",  
-         "\ua610"-"\ua61f",  "\ua62a"-"\ua62b",  "\ua640"-"\ua66e",  "\ua67f"-"\ua697",  "\ua6a0"-"\ua6ef",  
-         "\ua717"-"\ua71f",  "\ua722"-"\ua788",  "\ua78b"-"\ua78e",  "\ua790"-"\ua793",  "\ua7a0"-"\ua7aa",  
-         "\ua7f8"-"\ua801",  "\ua803"-"\ua805",  "\ua807"-"\ua80a",  "\ua80c"-"\ua822",  "\ua838",  "\ua840"-"\ua873",  
-         "\ua882"-"\ua8b3",  "\ua8f2"-"\ua8f7",  "\ua8fb",  "\ua90a"-"\ua925",  "\ua930"-"\ua946",  "\ua960"-"\ua97c",  
-         "\ua984"-"\ua9b2",  "\ua9cf",  "\uaa00"-"\uaa28",  "\uaa40"-"\uaa42",  "\uaa44"-"\uaa4b",  "\uaa60"-"\uaa76",  
-         "\uaa7a",  "\uaa80"-"\uaaaf",  "\uaab1",  "\uaab5"-"\uaab6",  "\uaab9"-"\uaabd",  "\uaac0",  "\uaac2",  
-         "\uaadb"-"\uaadd",  "\uaae0"-"\uaaea",  "\uaaf2"-"\uaaf4",  "\uab01"-"\uab06",  "\uab09"-"\uab0e",  
-         "\uab11"-"\uab16",  "\uab20"-"\uab26",  "\uab28"-"\uab2e",  "\uabc0"-"\uabe2",  "\uac00"-"\ud7a3",  
-         "\ud7b0"-"\ud7c6",  "\ud7cb"-"\ud7fb",  "\ud800"-"\udfff",  "\uf900"-"\ufa6d",  "\ufa70"-"\ufad9",  
-         "\ufb00"-"\ufb06",  "\ufb13"-"\ufb17",  "\ufb1d",  "\ufb1f"-"\ufb28",  "\ufb2a"-"\ufb36",  "\ufb38"-"\ufb3c",  
-         "\ufb3e",  "\ufb40"-"\ufb41",  "\ufb43"-"\ufb44",  "\ufb46"-"\ufbb1",  "\ufbd3"-"\ufd3d",  "\ufd50"-"\ufd8f",  
-         "\ufd92"-"\ufdc7",  "\ufdf0"-"\ufdfc",  "\ufe33"-"\ufe34",  "\ufe4d"-"\ufe4f",  "\ufe69",  "\ufe70"-"\ufe74",  
-         "\ufe76"-"\ufefc",  "\uff04",  "\uff21"-"\uff3a",  "\uff3f",  "\uff41"-"\uff5a",  "\uff66"-"\uffbe",  
-         "\uffc2"-"\uffc7",  "\uffca"-"\uffcf",  "\uffd2"-"\uffd7",  "\uffda"-"\uffdc",  "\uffe0"-"\uffe1",  
-         "\uffe5"-"\uffe6"  ]
+         "\u02ec",  "\u02ee",  "\u0370"-"\u0374",  "\u0376"-"\u0377",  "\u037a"-"\u037d",  "\u037f",  "\u0386",
+         "\u0388"-"\u038a",  "\u038c",  "\u038e"-"\u03a1",  "\u03a3"-"\u03f5",  "\u03f7"-"\u0481",  "\u048a"-"\u052f",
+         "\u0531"-"\u0556",  "\u0559",  "\u0561"-"\u0587",  "\u058f",  "\u05d0"-"\u05ea",  "\u05f0"-"\u05f2",
+         "\u060b",  "\u0620"-"\u064a",  "\u066e"-"\u066f",  "\u0671"-"\u06d3",  "\u06d5",  "\u06e5"-"\u06e6",
+         "\u06ee"-"\u06ef",  "\u06fa"-"\u06fc",  "\u06ff",  "\u0710",  "\u0712"-"\u072f",  "\u074d"-"\u07a5",
+         "\u07b1",  "\u07ca"-"\u07ea",  "\u07f4"-"\u07f5",  "\u07fa",  "\u0800"-"\u0815",  "\u081a",  "\u0824",
+         "\u0828",  "\u0840"-"\u0858",  "\u0860"-"\u086a",  "\u08a0"-"\u08b4",  "\u08b6"-"\u08bd",  "\u0904"-"\u0939",
+         "\u093d",  "\u0950",  "\u0958"-"\u0961",  "\u0971"-"\u0980",  "\u0985"-"\u098c",  "\u098f"-"\u0990",
+         "\u0993"-"\u09a8",  "\u09aa"-"\u09b0",  "\u09b2",  "\u09b6"-"\u09b9",  "\u09bd",  "\u09ce",  "\u09dc"-"\u09dd",
+         "\u09df"-"\u09e1",  "\u09f0"-"\u09f3",  "\u09fb"-"\u09fc",  "\u0a05"-"\u0a0a",  "\u0a0f"-"\u0a10",
+         "\u0a13"-"\u0a28",  "\u0a2a"-"\u0a30",  "\u0a32"-"\u0a33",  "\u0a35"-"\u0a36",  "\u0a38"-"\u0a39",
+         "\u0a59"-"\u0a5c",  "\u0a5e",  "\u0a72"-"\u0a74",  "\u0a85"-"\u0a8d",  "\u0a8f"-"\u0a91",  "\u0a93"-"\u0aa8",
+         "\u0aaa"-"\u0ab0",  "\u0ab2"-"\u0ab3",  "\u0ab5"-"\u0ab9",  "\u0abd",  "\u0ad0",  "\u0ae0"-"\u0ae1",
+         "\u0af1",  "\u0af9",  "\u0b05"-"\u0b0c",  "\u0b0f"-"\u0b10",  "\u0b13"-"\u0b28",  "\u0b2a"-"\u0b30",
+         "\u0b32"-"\u0b33",  "\u0b35"-"\u0b39",  "\u0b3d",  "\u0b5c"-"\u0b5d",  "\u0b5f"-"\u0b61",  "\u0b71",
+         "\u0b83",  "\u0b85"-"\u0b8a",  "\u0b8e"-"\u0b90",  "\u0b92"-"\u0b95",  "\u0b99"-"\u0b9a",  "\u0b9c",
+         "\u0b9e"-"\u0b9f",  "\u0ba3"-"\u0ba4",  "\u0ba8"-"\u0baa",  "\u0bae"-"\u0bb9",  "\u0bd0",  "\u0bf9",
+         "\u0c05"-"\u0c0c",  "\u0c0e"-"\u0c10",  "\u0c12"-"\u0c28",  "\u0c2a"-"\u0c39",  "\u0c3d",  "\u0c58"-"\u0c5a",
+         "\u0c60"-"\u0c61",  "\u0c80",  "\u0c85"-"\u0c8c",  "\u0c8e"-"\u0c90",  "\u0c92"-"\u0ca8",  "\u0caa"-"\u0cb3",
+         "\u0cb5"-"\u0cb9",  "\u0cbd",  "\u0cde",  "\u0ce0"-"\u0ce1",  "\u0cf1"-"\u0cf2",  "\u0d05"-"\u0d0c",
+         "\u0d0e"-"\u0d10",  "\u0d12"-"\u0d3a",  "\u0d3d",  "\u0d4e",  "\u0d54"-"\u0d56",  "\u0d5f"-"\u0d61",
+         "\u0d7a"-"\u0d7f",  "\u0d85"-"\u0d96",  "\u0d9a"-"\u0db1",  "\u0db3"-"\u0dbb",  "\u0dbd",  "\u0dc0"-"\u0dc6",
+         "\u0e01"-"\u0e30",  "\u0e32"-"\u0e33",  "\u0e3f"-"\u0e46",  "\u0e81"-"\u0e82",  "\u0e84",  "\u0e87"-"\u0e88",
+         "\u0e8a",  "\u0e8d",  "\u0e94"-"\u0e97",  "\u0e99"-"\u0e9f",  "\u0ea1"-"\u0ea3",  "\u0ea5",  "\u0ea7",
+         "\u0eaa"-"\u0eab",  "\u0ead"-"\u0eb0",  "\u0eb2"-"\u0eb3",  "\u0ebd",  "\u0ec0"-"\u0ec4",  "\u0ec6",
+         "\u0edc"-"\u0edf",  "\u0f00",  "\u0f40"-"\u0f47",  "\u0f49"-"\u0f6c",  "\u0f88"-"\u0f8c",  "\u1000"-"\u102a",
+         "\u103f",  "\u1050"-"\u1055",  "\u105a"-"\u105d",  "\u1061",  "\u1065"-"\u1066",  "\u106e"-"\u1070",
+         "\u1075"-"\u1081",  "\u108e",  "\u10a0"-"\u10c5",  "\u10c7",  "\u10cd",  "\u10d0"-"\u10fa",  "\u10fc"-"\u1248",
+         "\u124a"-"\u124d",  "\u1250"-"\u1256",  "\u1258",  "\u125a"-"\u125d",  "\u1260"-"\u1288",  "\u128a"-"\u128d",
+         "\u1290"-"\u12b0",  "\u12b2"-"\u12b5",  "\u12b8"-"\u12be",  "\u12c0",  "\u12c2"-"\u12c5",  "\u12c8"-"\u12d6",
+         "\u12d8"-"\u1310",  "\u1312"-"\u1315",  "\u1318"-"\u135a",  "\u1380"-"\u138f",  "\u13a0"-"\u13f5",
+         "\u13f8"-"\u13fd",  "\u1401"-"\u166c",  "\u166f"-"\u167f",  "\u1681"-"\u169a",  "\u16a0"-"\u16ea",
+         "\u16ee"-"\u16f8",  "\u1700"-"\u170c",  "\u170e"-"\u1711",  "\u1720"-"\u1731",  "\u1740"-"\u1751",
+         "\u1760"-"\u176c",  "\u176e"-"\u1770",  "\u1780"-"\u17b3",  "\u17d7",  "\u17db"-"\u17dc",  "\u1820"-"\u1877",
+         "\u1880"-"\u1884",  "\u1887"-"\u18a8",  "\u18aa",  "\u18b0"-"\u18f5",  "\u1900"-"\u191e",  "\u1950"-"\u196d",
+         "\u1970"-"\u1974",  "\u1980"-"\u19ab",  "\u19b0"-"\u19c9",  "\u1a00"-"\u1a16",  "\u1a20"-"\u1a54",
+         "\u1aa7",  "\u1b05"-"\u1b33",  "\u1b45"-"\u1b4b",  "\u1b83"-"\u1ba0",  "\u1bae"-"\u1baf",  "\u1bba"-"\u1be5",
+         "\u1c00"-"\u1c23",  "\u1c4d"-"\u1c4f",  "\u1c5a"-"\u1c7d",  "\u1c80"-"\u1c88",  "\u1ce9"-"\u1cec",
+         "\u1cee"-"\u1cf1",  "\u1cf5"-"\u1cf6",  "\u1d00"-"\u1dbf",  "\u1e00"-"\u1f15",  "\u1f18"-"\u1f1d",
+         "\u1f20"-"\u1f45",  "\u1f48"-"\u1f4d",  "\u1f50"-"\u1f57",  "\u1f59",  "\u1f5b",  "\u1f5d",  "\u1f5f"-"\u1f7d",
+         "\u1f80"-"\u1fb4",  "\u1fb6"-"\u1fbc",  "\u1fbe",  "\u1fc2"-"\u1fc4",  "\u1fc6"-"\u1fcc",  "\u1fd0"-"\u1fd3",
+         "\u1fd6"-"\u1fdb",  "\u1fe0"-"\u1fec",  "\u1ff2"-"\u1ff4",  "\u1ff6"-"\u1ffc",  "\u203f"-"\u2040",
+         "\u2054",  "\u2071",  "\u207f",  "\u2090"-"\u209c",  "\u20a0"-"\u20bf",  "\u2102",  "\u2107",  "\u210a"-"\u2113",
+         "\u2115",  "\u2119"-"\u211d",  "\u2124",  "\u2126",  "\u2128",  "\u212a"-"\u212d",  "\u212f"-"\u2139",
+         "\u213c"-"\u213f",  "\u2145"-"\u2149",  "\u214e",  "\u2160"-"\u2188",  "\u2c00"-"\u2c2e",  "\u2c30"-"\u2c5e",
+         "\u2c60"-"\u2ce4",  "\u2ceb"-"\u2cee",  "\u2cf2"-"\u2cf3",  "\u2d00"-"\u2d25",  "\u2d27",  "\u2d2d",
+         "\u2d30"-"\u2d67",  "\u2d6f",  "\u2d80"-"\u2d96",  "\u2da0"-"\u2da6",  "\u2da8"-"\u2dae",  "\u2db0"-"\u2db6",
+         "\u2db8"-"\u2dbe",  "\u2dc0"-"\u2dc6",  "\u2dc8"-"\u2dce",  "\u2dd0"-"\u2dd6",  "\u2dd8"-"\u2dde",
+         "\u2e2f",  "\u3005"-"\u3007",  "\u3021"-"\u3029",  "\u3031"-"\u3035",  "\u3038"-"\u303c",  "\u3041"-"\u3096",
+         "\u309d"-"\u309f",  "\u30a1"-"\u30fa",  "\u30fc"-"\u30ff",  "\u3105"-"\u312e",  "\u3131"-"\u318e",
+         "\u31a0"-"\u31ba",  "\u31f0"-"\u31ff",  "\u3400"-"\u4db5",  "\u4e00"-"\u9fea",  "\ua000"-"\ua48c",
+         "\ua4d0"-"\ua4fd",  "\ua500"-"\ua60c",  "\ua610"-"\ua61f",  "\ua62a"-"\ua62b",  "\ua640"-"\ua66e",
+         "\ua67f"-"\ua69d",  "\ua6a0"-"\ua6ef",  "\ua717"-"\ua71f",  "\ua722"-"\ua788",  "\ua78b"-"\ua7ae",
+         "\ua7b0"-"\ua7b7",  "\ua7f7"-"\ua801",  "\ua803"-"\ua805",  "\ua807"-"\ua80a",  "\ua80c"-"\ua822",
+         "\ua838",  "\ua840"-"\ua873",  "\ua882"-"\ua8b3",  "\ua8f2"-"\ua8f7",  "\ua8fb",  "\ua8fd",  "\ua90a"-"\ua925",
+         "\ua930"-"\ua946",  "\ua960"-"\ua97c",  "\ua984"-"\ua9b2",  "\ua9cf",  "\ua9e0"-"\ua9e4",  "\ua9e6"-"\ua9ef",
+         "\ua9fa"-"\ua9fe",  "\uaa00"-"\uaa28",  "\uaa40"-"\uaa42",  "\uaa44"-"\uaa4b",  "\uaa60"-"\uaa76",
+         "\uaa7a",  "\uaa7e"-"\uaaaf",  "\uaab1",  "\uaab5"-"\uaab6",  "\uaab9"-"\uaabd",  "\uaac0",  "\uaac2",
+         "\uaadb"-"\uaadd",  "\uaae0"-"\uaaea",  "\uaaf2"-"\uaaf4",  "\uab01"-"\uab06",  "\uab09"-"\uab0e",
+         "\uab11"-"\uab16",  "\uab20"-"\uab26",  "\uab28"-"\uab2e",  "\uab30"-"\uab5a",  "\uab5c"-"\uab65",
+         "\uab70"-"\uabe2",  "\uac00"-"\ud7a3",  "\ud7b0"-"\ud7c6",  "\ud7cb"-"\ud7fb",  "\ud800"-"\udfff",
+         "\uf900"-"\ufa6d",  "\ufa70"-"\ufad9",  "\ufb00"-"\ufb06",  "\ufb13"-"\ufb17",  "\ufb1d",  "\ufb1f"-"\ufb28",
+         "\ufb2a"-"\ufb36",  "\ufb38"-"\ufb3c",  "\ufb3e",  "\ufb40"-"\ufb41",  "\ufb43"-"\ufb44",  "\ufb46"-"\ufbb1",
+         "\ufbd3"-"\ufd3d",  "\ufd50"-"\ufd8f",  "\ufd92"-"\ufdc7",  "\ufdf0"-"\ufdfc",  "\ufe33"-"\ufe34",
+         "\ufe4d"-"\ufe4f",  "\ufe69",  "\ufe70"-"\ufe74",  "\ufe76"-"\ufefc",  "\uff04",  "\uff21"-"\uff3a",
+         "\uff3f",  "\uff41"-"\uff5a",  "\uff66"-"\uffbe",  "\uffc2"-"\uffc7",  "\uffca"-"\uffcf",  "\uffd2"-"\uffd7",
+         "\uffda"-"\uffdc",  "\uffe0"-"\uffe1",  "\uffe5"-"\uffe6"  ]
         | <UNICODE_ESCAPE>
   >
 |
   < #PART_LETTER: [
-         "\u0000"-"\u0008",  "\u000e"-"\u001b",  "\u0024",  "\u0030"-"\u0039",  "\u0041"-"\u005a",  "\u005f",  
-         "\u0061"-"\u007a",  "\u007f"-"\u009f",  "\u00a2"-"\u00a5",  "\u00aa",  "\u00ad",  "\u00b5",  "\u00ba",  
-         "\u00c0"-"\u00d6",  "\u00d8"-"\u00f6",  "\u00f8"-"\u02c1",  "\u02c6"-"\u02d1",  "\u02e0"-"\u02e4",  
-         "\u02ec",  "\u02ee",  "\u0300"-"\u0374",  "\u0376"-"\u0377",  "\u037a"-"\u037d",  "\u0386",  "\u0388"-"\u038a",  
-         "\u038c",  "\u038e"-"\u03a1",  "\u03a3"-"\u03f5",  "\u03f7"-"\u0481",  "\u0483"-"\u0487",  "\u048a"-"\u0527",  
-         "\u0531"-"\u0556",  "\u0559",  "\u0561"-"\u0587",  "\u058f",  "\u0591"-"\u05bd",  "\u05bf",  "\u05c1"-"\u05c2",  
-         "\u05c4"-"\u05c5",  "\u05c7",  "\u05d0"-"\u05ea",  "\u05f0"-"\u05f2",  "\u0600"-"\u0604",  "\u060b",  
-         "\u0610"-"\u061a",  "\u0620"-"\u0669",  "\u066e"-"\u06d3",  "\u06d5"-"\u06dd",  "\u06df"-"\u06e8",  
-         "\u06ea"-"\u06fc",  "\u06ff",  "\u070f"-"\u074a",  "\u074d"-"\u07b1",  "\u07c0"-"\u07f5",  "\u07fa",  
-         "\u0800"-"\u082d",  "\u0840"-"\u085b",  "\u08a0",  "\u08a2"-"\u08ac",  "\u08e4"-"\u08fe",  "\u0900"-"\u0963",  
-         "\u0966"-"\u096f",  "\u0971"-"\u0977",  "\u0979"-"\u097f",  "\u0981"-"\u0983",  "\u0985"-"\u098c",  
-         "\u098f"-"\u0990",  "\u0993"-"\u09a8",  "\u09aa"-"\u09b0",  "\u09b2",  "\u09b6"-"\u09b9",  "\u09bc"-"\u09c4",  
-         "\u09c7"-"\u09c8",  "\u09cb"-"\u09ce",  "\u09d7",  "\u09dc"-"\u09dd",  "\u09df"-"\u09e3",  "\u09e6"-"\u09f3",  
-         "\u09fb",  "\u0a01"-"\u0a03",  "\u0a05"-"\u0a0a",  "\u0a0f"-"\u0a10",  "\u0a13"-"\u0a28",  "\u0a2a"-"\u0a30",  
-         "\u0a32"-"\u0a33",  "\u0a35"-"\u0a36",  "\u0a38"-"\u0a39",  "\u0a3c",  "\u0a3e"-"\u0a42",  "\u0a47"-"\u0a48",  
-         "\u0a4b"-"\u0a4d",  "\u0a51",  "\u0a59"-"\u0a5c",  "\u0a5e",  "\u0a66"-"\u0a75",  "\u0a81"-"\u0a83",  
-         "\u0a85"-"\u0a8d",  "\u0a8f"-"\u0a91",  "\u0a93"-"\u0aa8",  "\u0aaa"-"\u0ab0",  "\u0ab2"-"\u0ab3",  
-         "\u0ab5"-"\u0ab9",  "\u0abc"-"\u0ac5",  "\u0ac7"-"\u0ac9",  "\u0acb"-"\u0acd",  "\u0ad0",  "\u0ae0"-"\u0ae3",  
-         "\u0ae6"-"\u0aef",  "\u0af1",  "\u0b01"-"\u0b03",  "\u0b05"-"\u0b0c",  "\u0b0f"-"\u0b10",  "\u0b13"-"\u0b28",  
-         "\u0b2a"-"\u0b30",  "\u0b32"-"\u0b33",  "\u0b35"-"\u0b39",  "\u0b3c"-"\u0b44",  "\u0b47"-"\u0b48",  
-         "\u0b4b"-"\u0b4d",  "\u0b56"-"\u0b57",  "\u0b5c"-"\u0b5d",  "\u0b5f"-"\u0b63",  "\u0b66"-"\u0b6f",  
-         "\u0b71",  "\u0b82"-"\u0b83",  "\u0b85"-"\u0b8a",  "\u0b8e"-"\u0b90",  "\u0b92"-"\u0b95",  "\u0b99"-"\u0b9a",  
-         "\u0b9c",  "\u0b9e"-"\u0b9f",  "\u0ba3"-"\u0ba4",  "\u0ba8"-"\u0baa",  "\u0bae"-"\u0bb9",  "\u0bbe"-"\u0bc2",  
-         "\u0bc6"-"\u0bc8",  "\u0bca"-"\u0bcd",  "\u0bd0",  "\u0bd7",  "\u0be6"-"\u0bef",  "\u0bf9",  "\u0c01"-"\u0c03",  
-         "\u0c05"-"\u0c0c",  "\u0c0e"-"\u0c10",  "\u0c12"-"\u0c28",  "\u0c2a"-"\u0c33",  "\u0c35"-"\u0c39",  
-         "\u0c3d"-"\u0c44",  "\u0c46"-"\u0c48",  "\u0c4a"-"\u0c4d",  "\u0c55"-"\u0c56",  "\u0c58"-"\u0c59",  
-         "\u0c60"-"\u0c63",  "\u0c66"-"\u0c6f",  "\u0c82"-"\u0c83",  "\u0c85"-"\u0c8c",  "\u0c8e"-"\u0c90",  
-         "\u0c92"-"\u0ca8",  "\u0caa"-"\u0cb3",  "\u0cb5"-"\u0cb9",  "\u0cbc"-"\u0cc4",  "\u0cc6"-"\u0cc8",  
-         "\u0cca"-"\u0ccd",  "\u0cd5"-"\u0cd6",  "\u0cde",  "\u0ce0"-"\u0ce3",  "\u0ce6"-"\u0cef",  "\u0cf1"-"\u0cf2",  
-         "\u0d02"-"\u0d03",  "\u0d05"-"\u0d0c",  "\u0d0e"-"\u0d10",  "\u0d12"-"\u0d3a",  "\u0d3d"-"\u0d44",  
-         "\u0d46"-"\u0d48",  "\u0d4a"-"\u0d4e",  "\u0d57",  "\u0d60"-"\u0d63",  "\u0d66"-"\u0d6f",  "\u0d7a"-"\u0d7f",  
-         "\u0d82"-"\u0d83",  "\u0d85"-"\u0d96",  "\u0d9a"-"\u0db1",  "\u0db3"-"\u0dbb",  "\u0dbd",  "\u0dc0"-"\u0dc6",  
-         "\u0dca",  "\u0dcf"-"\u0dd4",  "\u0dd6",  "\u0dd8"-"\u0ddf",  "\u0df2"-"\u0df3",  "\u0e01"-"\u0e3a",  
-         "\u0e3f"-"\u0e4e",  "\u0e50"-"\u0e59",  "\u0e81"-"\u0e82",  "\u0e84",  "\u0e87"-"\u0e88",  "\u0e8a",  
-         "\u0e8d",  "\u0e94"-"\u0e97",  "\u0e99"-"\u0e9f",  "\u0ea1"-"\u0ea3",  "\u0ea5",  "\u0ea7",  "\u0eaa"-"\u0eab",  
-         "\u0ead"-"\u0eb9",  "\u0ebb"-"\u0ebd",  "\u0ec0"-"\u0ec4",  "\u0ec6",  "\u0ec8"-"\u0ecd",  "\u0ed0"-"\u0ed9",  
-         "\u0edc"-"\u0edf",  "\u0f00",  "\u0f18"-"\u0f19",  "\u0f20"-"\u0f29",  "\u0f35",  "\u0f37",  "\u0f39",  
-         "\u0f3e"-"\u0f47",  "\u0f49"-"\u0f6c",  "\u0f71"-"\u0f84",  "\u0f86"-"\u0f97",  "\u0f99"-"\u0fbc",  
-         "\u0fc6",  "\u1000"-"\u1049",  "\u1050"-"\u109d",  "\u10a0"-"\u10c5",  "\u10c7",  "\u10cd",  "\u10d0"-"\u10fa",  
-         "\u10fc"-"\u1248",  "\u124a"-"\u124d",  "\u1250"-"\u1256",  "\u1258",  "\u125a"-"\u125d",  "\u1260"-"\u1288",  
-         "\u128a"-"\u128d",  "\u1290"-"\u12b0",  "\u12b2"-"\u12b5",  "\u12b8"-"\u12be",  "\u12c0",  "\u12c2"-"\u12c5",  
-         "\u12c8"-"\u12d6",  "\u12d8"-"\u1310",  "\u1312"-"\u1315",  "\u1318"-"\u135a",  "\u135d"-"\u135f",  
-         "\u1380"-"\u138f",  "\u13a0"-"\u13f4",  "\u1401"-"\u166c",  "\u166f"-"\u167f",  "\u1681"-"\u169a",  
-         "\u16a0"-"\u16ea",  "\u16ee"-"\u16f0",  "\u1700"-"\u170c",  "\u170e"-"\u1714",  "\u1720"-"\u1734",  
-         "\u1740"-"\u1753",  "\u1760"-"\u176c",  "\u176e"-"\u1770",  "\u1772"-"\u1773",  "\u1780"-"\u17d3",  
-         "\u17d7",  "\u17db"-"\u17dd",  "\u17e0"-"\u17e9",  "\u180b"-"\u180d",  "\u1810"-"\u1819",  "\u1820"-"\u1877",  
-         "\u1880"-"\u18aa",  "\u18b0"-"\u18f5",  "\u1900"-"\u191c",  "\u1920"-"\u192b",  "\u1930"-"\u193b",  
-         "\u1946"-"\u196d",  "\u1970"-"\u1974",  "\u1980"-"\u19ab",  "\u19b0"-"\u19c9",  "\u19d0"-"\u19d9",  
-         "\u1a00"-"\u1a1b",  "\u1a20"-"\u1a5e",  "\u1a60"-"\u1a7c",  "\u1a7f"-"\u1a89",  "\u1a90"-"\u1a99",  
-         "\u1aa7",  "\u1b00"-"\u1b4b",  "\u1b50"-"\u1b59",  "\u1b6b"-"\u1b73",  "\u1b80"-"\u1bf3",  "\u1c00"-"\u1c37",  
-         "\u1c40"-"\u1c49",  "\u1c4d"-"\u1c7d",  "\u1cd0"-"\u1cd2",  "\u1cd4"-"\u1cf6",  "\u1d00"-"\u1de6",  
-         "\u1dfc"-"\u1f15",  "\u1f18"-"\u1f1d",  "\u1f20"-"\u1f45",  "\u1f48"-"\u1f4d",  "\u1f50"-"\u1f57",  
-         "\u1f59",  "\u1f5b",  "\u1f5d",  "\u1f5f"-"\u1f7d",  "\u1f80"-"\u1fb4",  "\u1fb6"-"\u1fbc",  "\u1fbe",  
-         "\u1fc2"-"\u1fc4",  "\u1fc6"-"\u1fcc",  "\u1fd0"-"\u1fd3",  "\u1fd6"-"\u1fdb",  "\u1fe0"-"\u1fec",  
-         "\u1ff2"-"\u1ff4",  "\u1ff6"-"\u1ffc",  "\u200b"-"\u200f",  "\u202a"-"\u202e",  "\u203f"-"\u2040",  
-         "\u2054",  "\u2060"-"\u2064",  "\u206a"-"\u206f",  "\u2071",  "\u207f",  "\u2090"-"\u209c",  "\u20a0"-"\u20ba",  
-         "\u20d0"-"\u20dc",  "\u20e1",  "\u20e5"-"\u20f0",  "\u2102",  "\u2107",  "\u210a"-"\u2113",  "\u2115",  
-         "\u2119"-"\u211d",  "\u2124",  "\u2126",  "\u2128",  "\u212a"-"\u212d",  "\u212f"-"\u2139",  "\u213c"-"\u213f",  
-         "\u2145"-"\u2149",  "\u214e",  "\u2160"-"\u2188",  "\u2c00"-"\u2c2e",  "\u2c30"-"\u2c5e",  "\u2c60"-"\u2ce4",  
-         "\u2ceb"-"\u2cf3",  "\u2d00"-"\u2d25",  "\u2d27",  "\u2d2d",  "\u2d30"-"\u2d67",  "\u2d6f",  "\u2d7f"-"\u2d96",  
-         "\u2da0"-"\u2da6",  "\u2da8"-"\u2dae",  "\u2db0"-"\u2db6",  "\u2db8"-"\u2dbe",  "\u2dc0"-"\u2dc6",  
-         "\u2dc8"-"\u2dce",  "\u2dd0"-"\u2dd6",  "\u2dd8"-"\u2dde",  "\u2de0"-"\u2dff",  "\u2e2f",  "\u3005"-"\u3007",  
-         "\u3021"-"\u302f",  "\u3031"-"\u3035",  "\u3038"-"\u303c",  "\u3041"-"\u3096",  "\u3099"-"\u309a",  
-         "\u309d"-"\u309f",  "\u30a1"-"\u30fa",  "\u30fc"-"\u30ff",  "\u3105"-"\u312d",  "\u3131"-"\u318e",  
-         "\u31a0"-"\u31ba",  "\u31f0"-"\u31ff",  "\u3400"-"\u4db5",  "\u4e00"-"\u9fcc",  "\ua000"-"\ua48c",  
-         "\ua4d0"-"\ua4fd",  "\ua500"-"\ua60c",  "\ua610"-"\ua62b",  "\ua640"-"\ua66f",  "\ua674"-"\ua67d",  
-         "\ua67f"-"\ua697",  "\ua69f"-"\ua6f1",  "\ua717"-"\ua71f",  "\ua722"-"\ua788",  "\ua78b"-"\ua78e",  
-         "\ua790"-"\ua793",  "\ua7a0"-"\ua7aa",  "\ua7f8"-"\ua827",  "\ua838",  "\ua840"-"\ua873",  "\ua880"-"\ua8c4",  
-         "\ua8d0"-"\ua8d9",  "\ua8e0"-"\ua8f7",  "\ua8fb",  "\ua900"-"\ua92d",  "\ua930"-"\ua953",  "\ua960"-"\ua97c",  
-         "\ua980"-"\ua9c0",  "\ua9cf"-"\ua9d9",  "\uaa00"-"\uaa36",  "\uaa40"-"\uaa4d",  "\uaa50"-"\uaa59",  
-         "\uaa60"-"\uaa76",  "\uaa7a"-"\uaa7b",  "\uaa80"-"\uaac2",  "\uaadb"-"\uaadd",  "\uaae0"-"\uaaef",  
-         "\uaaf2"-"\uaaf6",  "\uab01"-"\uab06",  "\uab09"-"\uab0e",  "\uab11"-"\uab16",  "\uab20"-"\uab26",  
-         "\uab28"-"\uab2e",  "\uabc0"-"\uabea",  "\uabec"-"\uabed",  "\uabf0"-"\uabf9",  "\uac00"-"\ud7a3",  
-         "\ud7b0"-"\ud7c6",  "\ud7cb"-"\ud7fb",  "\ud800"-"\udfff",  "\uf900"-"\ufa6d",  "\ufa70"-"\ufad9",  
-         "\ufb00"-"\ufb06",  "\ufb13"-"\ufb17",  "\ufb1d"-"\ufb28",  "\ufb2a"-"\ufb36",  "\ufb38"-"\ufb3c",  
-         "\ufb3e",  "\ufb40"-"\ufb41",  "\ufb43"-"\ufb44",  "\ufb46"-"\ufbb1",  "\ufbd3"-"\ufd3d",  "\ufd50"-"\ufd8f",  
-         "\ufd92"-"\ufdc7",  "\ufdf0"-"\ufdfc",  "\ufe00"-"\ufe0f",  "\ufe20"-"\ufe26",  "\ufe33"-"\ufe34",  
-         "\ufe4d"-"\ufe4f",  "\ufe69",  "\ufe70"-"\ufe74",  "\ufe76"-"\ufefc",  "\ufeff",  "\uff04",  "\uff10"-"\uff19",  
-         "\uff21"-"\uff3a",  "\uff3f",  "\uff41"-"\uff5a",  "\uff66"-"\uffbe",  "\uffc2"-"\uffc7",  "\uffca"-"\uffcf",  
-         "\uffd2"-"\uffd7",  "\uffda"-"\uffdc",  "\uffe0"-"\uffe1",  "\uffe5"-"\uffe6",  "\ufff9"-"\ufffb" ]
+         "\u0000"-"\u0008",  "\u000e"-"\u001b",  "\u0024",  "\u0030"-"\u0039",  "\u0041"-"\u005a",  "\u005f",
+         "\u0061"-"\u007a",  "\u007f"-"\u009f",  "\u00a2"-"\u00a5",  "\u00aa",  "\u00ad",  "\u00b5",  "\u00ba",
+         "\u00c0"-"\u00d6",  "\u00d8"-"\u00f6",  "\u00f8"-"\u02c1",  "\u02c6"-"\u02d1",  "\u02e0"-"\u02e4",
+         "\u02ec",  "\u02ee",  "\u0300"-"\u0374",  "\u0376"-"\u0377",  "\u037a"-"\u037d",  "\u037f",  "\u0386",
+         "\u0388"-"\u038a",  "\u038c",  "\u038e"-"\u03a1",  "\u03a3"-"\u03f5",  "\u03f7"-"\u0481",  "\u0483"-"\u0487",
+         "\u048a"-"\u052f",  "\u0531"-"\u0556",  "\u0559",  "\u0561"-"\u0587",  "\u058f",  "\u0591"-"\u05bd",
+         "\u05bf",  "\u05c1"-"\u05c2",  "\u05c4"-"\u05c5",  "\u05c7",  "\u05d0"-"\u05ea",  "\u05f0"-"\u05f2",
+         "\u0600"-"\u0605",  "\u060b",  "\u0610"-"\u061a",  "\u061c",  "\u0620"-"\u0669",  "\u066e"-"\u06d3",
+         "\u06d5"-"\u06dd",  "\u06df"-"\u06e8",  "\u06ea"-"\u06fc",  "\u06ff",  "\u070f"-"\u074a",  "\u074d"-"\u07b1",
+         "\u07c0"-"\u07f5",  "\u07fa",  "\u0800"-"\u082d",  "\u0840"-"\u085b",  "\u0860"-"\u086a",  "\u08a0"-"\u08b4",
+         "\u08b6"-"\u08bd",  "\u08d4"-"\u0963",  "\u0966"-"\u096f",  "\u0971"-"\u0983",  "\u0985"-"\u098c",
+         "\u098f"-"\u0990",  "\u0993"-"\u09a8",  "\u09aa"-"\u09b0",  "\u09b2",  "\u09b6"-"\u09b9",  "\u09bc"-"\u09c4",
+         "\u09c7"-"\u09c8",  "\u09cb"-"\u09ce",  "\u09d7",  "\u09dc"-"\u09dd",  "\u09df"-"\u09e3",  "\u09e6"-"\u09f3",
+         "\u09fb"-"\u09fc",  "\u0a01"-"\u0a03",  "\u0a05"-"\u0a0a",  "\u0a0f"-"\u0a10",  "\u0a13"-"\u0a28",
+         "\u0a2a"-"\u0a30",  "\u0a32"-"\u0a33",  "\u0a35"-"\u0a36",  "\u0a38"-"\u0a39",  "\u0a3c",  "\u0a3e"-"\u0a42",
+         "\u0a47"-"\u0a48",  "\u0a4b"-"\u0a4d",  "\u0a51",  "\u0a59"-"\u0a5c",  "\u0a5e",  "\u0a66"-"\u0a75",
+         "\u0a81"-"\u0a83",  "\u0a85"-"\u0a8d",  "\u0a8f"-"\u0a91",  "\u0a93"-"\u0aa8",  "\u0aaa"-"\u0ab0",
+         "\u0ab2"-"\u0ab3",  "\u0ab5"-"\u0ab9",  "\u0abc"-"\u0ac5",  "\u0ac7"-"\u0ac9",  "\u0acb"-"\u0acd",
+         "\u0ad0",  "\u0ae0"-"\u0ae3",  "\u0ae6"-"\u0aef",  "\u0af1",  "\u0af9"-"\u0aff",  "\u0b01"-"\u0b03",
+         "\u0b05"-"\u0b0c",  "\u0b0f"-"\u0b10",  "\u0b13"-"\u0b28",  "\u0b2a"-"\u0b30",  "\u0b32"-"\u0b33",
+         "\u0b35"-"\u0b39",  "\u0b3c"-"\u0b44",  "\u0b47"-"\u0b48",  "\u0b4b"-"\u0b4d",  "\u0b56"-"\u0b57",
+         "\u0b5c"-"\u0b5d",  "\u0b5f"-"\u0b63",  "\u0b66"-"\u0b6f",  "\u0b71",  "\u0b82"-"\u0b83",  "\u0b85"-"\u0b8a",
+         "\u0b8e"-"\u0b90",  "\u0b92"-"\u0b95",  "\u0b99"-"\u0b9a",  "\u0b9c",  "\u0b9e"-"\u0b9f",  "\u0ba3"-"\u0ba4",
+         "\u0ba8"-"\u0baa",  "\u0bae"-"\u0bb9",  "\u0bbe"-"\u0bc2",  "\u0bc6"-"\u0bc8",  "\u0bca"-"\u0bcd",
+         "\u0bd0",  "\u0bd7",  "\u0be6"-"\u0bef",  "\u0bf9",  "\u0c00"-"\u0c03",  "\u0c05"-"\u0c0c",  "\u0c0e"-"\u0c10",
+         "\u0c12"-"\u0c28",  "\u0c2a"-"\u0c39",  "\u0c3d"-"\u0c44",  "\u0c46"-"\u0c48",  "\u0c4a"-"\u0c4d",
+         "\u0c55"-"\u0c56",  "\u0c58"-"\u0c5a",  "\u0c60"-"\u0c63",  "\u0c66"-"\u0c6f",  "\u0c80"-"\u0c83",
+         "\u0c85"-"\u0c8c",  "\u0c8e"-"\u0c90",  "\u0c92"-"\u0ca8",  "\u0caa"-"\u0cb3",  "\u0cb5"-"\u0cb9",
+         "\u0cbc"-"\u0cc4",  "\u0cc6"-"\u0cc8",  "\u0cca"-"\u0ccd",  "\u0cd5"-"\u0cd6",  "\u0cde",  "\u0ce0"-"\u0ce3",
+         "\u0ce6"-"\u0cef",  "\u0cf1"-"\u0cf2",  "\u0d00"-"\u0d03",  "\u0d05"-"\u0d0c",  "\u0d0e"-"\u0d10",
+         "\u0d12"-"\u0d44",  "\u0d46"-"\u0d48",  "\u0d4a"-"\u0d4e",  "\u0d54"-"\u0d57",  "\u0d5f"-"\u0d63",
+         "\u0d66"-"\u0d6f",  "\u0d7a"-"\u0d7f",  "\u0d82"-"\u0d83",  "\u0d85"-"\u0d96",  "\u0d9a"-"\u0db1",
+         "\u0db3"-"\u0dbb",  "\u0dbd",  "\u0dc0"-"\u0dc6",  "\u0dca",  "\u0dcf"-"\u0dd4",  "\u0dd6",  "\u0dd8"-"\u0ddf",
+         "\u0de6"-"\u0def",  "\u0df2"-"\u0df3",  "\u0e01"-"\u0e3a",  "\u0e3f"-"\u0e4e",  "\u0e50"-"\u0e59",
+         "\u0e81"-"\u0e82",  "\u0e84",  "\u0e87"-"\u0e88",  "\u0e8a",  "\u0e8d",  "\u0e94"-"\u0e97",  "\u0e99"-"\u0e9f",
+         "\u0ea1"-"\u0ea3",  "\u0ea5",  "\u0ea7",  "\u0eaa"-"\u0eab",  "\u0ead"-"\u0eb9",  "\u0ebb"-"\u0ebd",
+         "\u0ec0"-"\u0ec4",  "\u0ec6",  "\u0ec8"-"\u0ecd",  "\u0ed0"-"\u0ed9",  "\u0edc"-"\u0edf",  "\u0f00",
+         "\u0f18"-"\u0f19",  "\u0f20"-"\u0f29",  "\u0f35",  "\u0f37",  "\u0f39",  "\u0f3e"-"\u0f47",  "\u0f49"-"\u0f6c",
+         "\u0f71"-"\u0f84",  "\u0f86"-"\u0f97",  "\u0f99"-"\u0fbc",  "\u0fc6",  "\u1000"-"\u1049",  "\u1050"-"\u109d",
+         "\u10a0"-"\u10c5",  "\u10c7",  "\u10cd",  "\u10d0"-"\u10fa",  "\u10fc"-"\u1248",  "\u124a"-"\u124d",
+         "\u1250"-"\u1256",  "\u1258",  "\u125a"-"\u125d",  "\u1260"-"\u1288",  "\u128a"-"\u128d",  "\u1290"-"\u12b0",
+         "\u12b2"-"\u12b5",  "\u12b8"-"\u12be",  "\u12c0",  "\u12c2"-"\u12c5",  "\u12c8"-"\u12d6",  "\u12d8"-"\u1310",
+         "\u1312"-"\u1315",  "\u1318"-"\u135a",  "\u135d"-"\u135f",  "\u1380"-"\u138f",  "\u13a0"-"\u13f5",
+         "\u13f8"-"\u13fd",  "\u1401"-"\u166c",  "\u166f"-"\u167f",  "\u1681"-"\u169a",  "\u16a0"-"\u16ea",
+         "\u16ee"-"\u16f8",  "\u1700"-"\u170c",  "\u170e"-"\u1714",  "\u1720"-"\u1734",  "\u1740"-"\u1753",
+         "\u1760"-"\u176c",  "\u176e"-"\u1770",  "\u1772"-"\u1773",  "\u1780"-"\u17d3",  "\u17d7",  "\u17db"-"\u17dd",
+         "\u17e0"-"\u17e9",  "\u180b"-"\u180e",  "\u1810"-"\u1819",  "\u1820"-"\u1877",  "\u1880"-"\u18aa",
+         "\u18b0"-"\u18f5",  "\u1900"-"\u191e",  "\u1920"-"\u192b",  "\u1930"-"\u193b",  "\u1946"-"\u196d",
+         "\u1970"-"\u1974",  "\u1980"-"\u19ab",  "\u19b0"-"\u19c9",  "\u19d0"-"\u19d9",  "\u1a00"-"\u1a1b",
+         "\u1a20"-"\u1a5e",  "\u1a60"-"\u1a7c",  "\u1a7f"-"\u1a89",  "\u1a90"-"\u1a99",  "\u1aa7",  "\u1ab0"-"\u1abd",
+         "\u1b00"-"\u1b4b",  "\u1b50"-"\u1b59",  "\u1b6b"-"\u1b73",  "\u1b80"-"\u1bf3",  "\u1c00"-"\u1c37",
+         "\u1c40"-"\u1c49",  "\u1c4d"-"\u1c7d",  "\u1c80"-"\u1c88",  "\u1cd0"-"\u1cd2",  "\u1cd4"-"\u1cf9",
+         "\u1d00"-"\u1df9",  "\u1dfb"-"\u1f15",  "\u1f18"-"\u1f1d",  "\u1f20"-"\u1f45",  "\u1f48"-"\u1f4d",
+         "\u1f50"-"\u1f57",  "\u1f59",  "\u1f5b",  "\u1f5d",  "\u1f5f"-"\u1f7d",  "\u1f80"-"\u1fb4",  "\u1fb6"-"\u1fbc",
+         "\u1fbe",  "\u1fc2"-"\u1fc4",  "\u1fc6"-"\u1fcc",  "\u1fd0"-"\u1fd3",  "\u1fd6"-"\u1fdb",  "\u1fe0"-"\u1fec",
+         "\u1ff2"-"\u1ff4",  "\u1ff6"-"\u1ffc",  "\u200b"-"\u200f",  "\u202a"-"\u202e",  "\u203f"-"\u2040",
+         "\u2054",  "\u2060"-"\u2064",  "\u2066"-"\u206f",  "\u2071",  "\u207f",  "\u2090"-"\u209c",  "\u20a0"-"\u20bf",
+         "\u20d0"-"\u20dc",  "\u20e1",  "\u20e5"-"\u20f0",  "\u2102",  "\u2107",  "\u210a"-"\u2113",  "\u2115",
+         "\u2119"-"\u211d",  "\u2124",  "\u2126",  "\u2128",  "\u212a"-"\u212d",  "\u212f"-"\u2139",  "\u213c"-"\u213f",
+         "\u2145"-"\u2149",  "\u214e",  "\u2160"-"\u2188",  "\u2c00"-"\u2c2e",  "\u2c30"-"\u2c5e",  "\u2c60"-"\u2ce4",
+         "\u2ceb"-"\u2cf3",  "\u2d00"-"\u2d25",  "\u2d27",  "\u2d2d",  "\u2d30"-"\u2d67",  "\u2d6f",  "\u2d7f"-"\u2d96",
+         "\u2da0"-"\u2da6",  "\u2da8"-"\u2dae",  "\u2db0"-"\u2db6",  "\u2db8"-"\u2dbe",  "\u2dc0"-"\u2dc6",
+         "\u2dc8"-"\u2dce",  "\u2dd0"-"\u2dd6",  "\u2dd8"-"\u2dde",  "\u2de0"-"\u2dff",  "\u2e2f",  "\u3005"-"\u3007",
+         "\u3021"-"\u302f",  "\u3031"-"\u3035",  "\u3038"-"\u303c",  "\u3041"-"\u3096",  "\u3099"-"\u309a",
+         "\u309d"-"\u309f",  "\u30a1"-"\u30fa",  "\u30fc"-"\u30ff",  "\u3105"-"\u312e",  "\u3131"-"\u318e",
+         "\u31a0"-"\u31ba",  "\u31f0"-"\u31ff",  "\u3400"-"\u4db5",  "\u4e00"-"\u9fea",  "\ua000"-"\ua48c",
+         "\ua4d0"-"\ua4fd",  "\ua500"-"\ua60c",  "\ua610"-"\ua62b",  "\ua640"-"\ua66f",  "\ua674"-"\ua67d",
+         "\ua67f"-"\ua6f1",  "\ua717"-"\ua71f",  "\ua722"-"\ua788",  "\ua78b"-"\ua7ae",  "\ua7b0"-"\ua7b7",
+         "\ua7f7"-"\ua827",  "\ua838",  "\ua840"-"\ua873",  "\ua880"-"\ua8c5",  "\ua8d0"-"\ua8d9",  "\ua8e0"-"\ua8f7",
+         "\ua8fb",  "\ua8fd",  "\ua900"-"\ua92d",  "\ua930"-"\ua953",  "\ua960"-"\ua97c",  "\ua980"-"\ua9c0",
+         "\ua9cf"-"\ua9d9",  "\ua9e0"-"\ua9fe",  "\uaa00"-"\uaa36",  "\uaa40"-"\uaa4d",  "\uaa50"-"\uaa59",
+         "\uaa60"-"\uaa76",  "\uaa7a"-"\uaac2",  "\uaadb"-"\uaadd",  "\uaae0"-"\uaaef",  "\uaaf2"-"\uaaf6",
+         "\uab01"-"\uab06",  "\uab09"-"\uab0e",  "\uab11"-"\uab16",  "\uab20"-"\uab26",  "\uab28"-"\uab2e",
+         "\uab30"-"\uab5a",  "\uab5c"-"\uab65",  "\uab70"-"\uabea",  "\uabec"-"\uabed",  "\uabf0"-"\uabf9",
+         "\uac00"-"\ud7a3",  "\ud7b0"-"\ud7c6",  "\ud7cb"-"\ud7fb",  "\ud800"-"\udfff",  "\uf900"-"\ufa6d",
+         "\ufa70"-"\ufad9",  "\ufb00"-"\ufb06",  "\ufb13"-"\ufb17",  "\ufb1d"-"\ufb28",  "\ufb2a"-"\ufb36",
+         "\ufb38"-"\ufb3c",  "\ufb3e",  "\ufb40"-"\ufb41",  "\ufb43"-"\ufb44",  "\ufb46"-"\ufbb1",  "\ufbd3"-"\ufd3d",
+         "\ufd50"-"\ufd8f",  "\ufd92"-"\ufdc7",  "\ufdf0"-"\ufdfc",  "\ufe00"-"\ufe0f",  "\ufe20"-"\ufe2f",
+         "\ufe33"-"\ufe34",  "\ufe4d"-"\ufe4f",  "\ufe69",  "\ufe70"-"\ufe74",  "\ufe76"-"\ufefc",  "\ufeff",
+         "\uff04",  "\uff10"-"\uff19",  "\uff21"-"\uff3a",  "\uff3f",  "\uff41"-"\uff5a",  "\uff66"-"\uffbe",
+         "\uffc2"-"\uffc7",  "\uffca"-"\uffcf",  "\uffd2"-"\uffd7",  "\uffda"-"\uffdc",  "\uffe0"-"\uffe1",
+         "\uffe5"-"\uffe6",  "\ufff9"-"\ufffb" ]
         | <UNICODE_ESCAPE>
   >
 }
@@ -611,8 +615,8 @@
 	NodeList<ImportDeclaration> imports = emptyList();
 	ImportDeclaration in = null;
 	NodeList<TypeDeclaration<?>> types = emptyList();
-   ModifierHolder modifier;
-	TypeDeclaration tn = null;
+    ModifierHolder modifier;
+	TypeDeclaration<?> tn = null;
 	ModuleDeclaration module = null;
 }
 {
@@ -684,7 +688,7 @@
 ModifierHolder Modifiers():
 {
 	JavaToken begin = INVALID;
-    EnumSet<Modifier> modifiers = EnumSet.noneOf(Modifier.class);
+    NodeList<Modifier> modifiers = new NodeList<Modifier>();
 	NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>();
     AnnotationExpr ann;
 }
@@ -692,31 +696,31 @@
  (
   LOOKAHEAD(2)
   (
-   "public" { addModifier(modifiers, Modifier.PUBLIC); begin = orIfInvalid(begin, token()); }
+   "public" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PUBLIC)); begin = orIfInvalid(begin, token()); }
   |
-   "static" { addModifier(modifiers, Modifier.STATIC); begin = orIfInvalid(begin, token()); }
+   "static" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.STATIC)); begin = orIfInvalid(begin, token()); }
   |
-   "protected" {  addModifier(modifiers, Modifier.PROTECTED); begin = orIfInvalid(begin, token()); }
+   "protected" {  add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PROTECTED)); begin = orIfInvalid(begin, token()); }
   |
-   "private" { addModifier(modifiers, Modifier.PRIVATE); begin = orIfInvalid(begin, token()); }
+   "private" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.PRIVATE)); begin = orIfInvalid(begin, token()); }
   |
-   "final" { addModifier(modifiers, Modifier.FINAL); begin = orIfInvalid(begin, token()); }
+   "final" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.FINAL)); begin = orIfInvalid(begin, token()); }
   |
-   "abstract" { addModifier(modifiers, Modifier.ABSTRACT); begin = orIfInvalid(begin, token()); }
+   "abstract" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.ABSTRACT)); begin = orIfInvalid(begin, token()); }
   |
-   "synchronized" { addModifier(modifiers, Modifier.SYNCHRONIZED); begin = orIfInvalid(begin, token()); }
+   "synchronized" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.SYNCHRONIZED)); begin = orIfInvalid(begin, token()); }
   |
-   "native" { addModifier(modifiers, Modifier.NATIVE); begin = orIfInvalid(begin, token()); }
+   "native" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.NATIVE)); begin = orIfInvalid(begin, token()); }
   |
-   "transient" { addModifier(modifiers, Modifier.TRANSIENT); begin = orIfInvalid(begin, token()); }
+   "transient" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.TRANSIENT)); begin = orIfInvalid(begin, token()); }
   |
-   "volatile" { addModifier(modifiers, Modifier.VOLATILE); begin = orIfInvalid(begin, token()); }
+   "volatile" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.VOLATILE)); begin = orIfInvalid(begin, token()); }
   |
-   "strictfp" { addModifier(modifiers, Modifier.STRICTFP);  begin = orIfInvalid(begin, token()); }
+   "strictfp" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.STRICTFP));  begin = orIfInvalid(begin, token()); }
   |
-   "transitive" { addModifier(modifiers, Modifier.TRANSITIVE);  begin = orIfInvalid(begin, token()); }
+   "transitive" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.TRANSITIVE));  begin = orIfInvalid(begin, token()); }
   |
-   "default" { addModifier(modifiers, Modifier.DEFAULT);  begin = orIfInvalid(begin, token()); }
+   "default" { add(modifiers, new Modifier(tokenRange(), Modifier.Keyword.DEFAULT));  begin = orIfInvalid(begin, token()); }
   |
    ann = Annotation() { annotations = add(annotations, ann); begin = orIfInvalid(begin, ann); }
   )
@@ -1067,9 +1071,9 @@
     Pair<SimpleName, List<ArrayBracketPair>> id;
 }
 {
-    id = VariableDeclaratorId() 	{ ret = add(ret, new Parameter(range(id.a, id.a), EnumSet.noneOf(Modifier.class), emptyList(), new UnknownType(), false, emptyList(), id.a));}
+    id = VariableDeclaratorId() 	{ ret = add(ret, new Parameter(range(id.a, id.a), new NodeList<Modifier>(), emptyList(), new UnknownType(), false, emptyList(), id.a));}
     (
-        "," id = VariableDeclaratorId()  { ret = add(ret, new Parameter(range(id.a, id.a), EnumSet.noneOf(Modifier.class), emptyList(), new UnknownType(), false, emptyList(), id.a)); }
+        "," id = VariableDeclaratorId()  { ret = add(ret, new Parameter(range(id.a, id.a), new NodeList<Modifier>(), emptyList(), new UnknownType(), false, emptyList(), id.a)); }
     )*
     { return ret;  }
 }
@@ -1109,11 +1113,10 @@
 Name ReceiverParameterId():
 {
 	Name ret = null;
-	NodeList<AnnotationExpr> annotations;
 }
 {
-    [ LOOKAHEAD(Name()) ret = Name() "."] annotations=Annotations() "this" 
-    { return new Name(tokenRange(), ret, token.image, annotations); }
+    [ LOOKAHEAD(Name()) ret = Name() "."] "this" 
+    { return new Name(tokenRange(), ret, token.image); }
 }
 
 ConstructorDeclaration ConstructorDeclaration(ModifierHolder modifier):
@@ -1381,12 +1384,10 @@
  */
 {
 	Name ret;
-	NodeList<AnnotationExpr> annotations = new NodeList<AnnotationExpr>();
 }
 {
-  annotations=Annotations() Identifier() { ret = new Name(tokenRange(), null, token.image, annotations); }
-  ( LOOKAHEAD("." Annotations() Identifier()) 
-  "." annotations=Annotations() Identifier() { ret = new Name(range(ret, token()), ret, token.image, annotations); } )*
+  Identifier() { ret = new Name(tokenRange(), null, token.image); }
+  ( LOOKAHEAD(2) "." Identifier() { ret = new Name(range(ret, token()), ret, token.image); } )*
   { return ret; }
 }
 
@@ -1693,17 +1694,19 @@
 	JavaToken begin = INVALID;
 }
 {
-  (
-	  ( "~" { op = UnaryExpr.Operator.BITWISE_COMPLEMENT; begin=token(); } |
-	    "!" { op = UnaryExpr.Operator.LOGICAL_COMPLEMENT;     begin=token(); }
-	  ) ret = UnaryExpression() { ret = new UnaryExpr(range(begin, token()), ret, op); }
-	|
-	  LOOKAHEAD( CastExpression() )
-	  ret = CastExpression()
-	|
-      ret = PostfixExpression()
-  )
-  { return ret; }
+	(
+		(
+			"~" { op = UnaryExpr.Operator.BITWISE_COMPLEMENT; begin=token(); } |
+			"!" { op = UnaryExpr.Operator.LOGICAL_COMPLEMENT;     begin=token(); }
+		) ret = UnaryExpression() { ret = new UnaryExpr(range(begin, token()), ret, op); }
+		| LOOKAHEAD( CastExpression() )
+			ret = CastExpression()
+		|
+			ret = PostfixExpression()
+		|
+			ret = SwitchExpression()
+	)
+	{ return ret; }
 }
 
 Expression PostfixExpression():
@@ -1861,7 +1864,7 @@
   	LOOKAHEAD(2)
 	ret = PrimarySuffixWithoutSuper(scope)
 	|
-  	"." "super" { ret = new SuperExpr(range(scope, token()), scope); }
+  	"." "super" { ret = new SuperExpr(range(scope, token()), scopeToName(scope)); }
   )
   { return ret; }
 }
@@ -1878,7 +1881,7 @@
   (
   	"."
   	(
-		"this" { ret = new ThisExpr(range(scope, token()), scope); }
+		"this" { ret = new ThisExpr(range(scope, token()), scopeToName(scope)); }
 	  |
 	  	ret = AllocationExpression(scope)
 	  |
@@ -1985,13 +1988,13 @@
 {
     "new" { if(scope==null) {begin=token();} else {begin = orIfInvalid(begin, scope);} }
     
+    [ typeArgs = TypeArguments() ]
     annotations = Annotations() 
     (
         type = PrimitiveType(annotations)
         ret = ArrayCreation(begin, type)
     |
-        [ typeArgs = TypeArguments() ]
-        type = AnnotatedClassOrInterfaceType()
+        type = ClassOrInterfaceType(annotations)
         (
             ret = ArrayCreation(begin, type)
         |
@@ -2215,8 +2218,8 @@
 SwitchStmt SwitchStatement():
 {
 	Expression selector;
-	SwitchEntryStmt entry;
-	NodeList<SwitchEntryStmt> entries = emptyList();
+	SwitchEntry entry;
+	NodeList<SwitchEntry> entries = emptyList();
 	JavaToken begin;
 }
 {
@@ -2227,21 +2230,63 @@
   { return new SwitchStmt(range(begin, token()), selector, entries); }
 }
 
-SwitchEntryStmt SwitchEntry():
+SwitchExpr SwitchExpression():
 {
-	Expression label = null;
-	NodeList<Statement> stmts;
+	Expression selector;
+	SwitchEntry entry;
+	NodeList<SwitchEntry> entries = emptyList();
 	JavaToken begin;
 }
 {
-  (
-	  "case" {begin=token();} label = Expression()
-	|
-	  "default" {begin=token();}
-  )
-  ":" stmts = Statements()
+  "switch" {begin=token();} "(" selector = Expression() ")" "{"
+    ( entry = SwitchEntry() { entries = add(entries, entry); } )*
+  "}"
 
-  { return new SwitchEntryStmt(range(begin, token()),label, stmts); }
+  { return new SwitchExpr(range(begin, token()), selector, entries); }
+}
+
+SwitchEntry SwitchEntry():
+{
+	Expression label = null;
+	NodeList<Expression> labels = emptyList();
+	NodeList<Statement> stmts = emptyList();
+	JavaToken begin;
+	SwitchEntry ret;
+	Expression expression = null;
+	Statement stmt = null;
+}
+{
+	(
+		"case" {begin=token();} label = ConditionalExpression() { labels = add(labels, label); }
+		( "," label = ConditionalExpression()  { labels = add(labels, label); } )*
+	|
+		"default" {begin=token();}
+	)
+    (
+        ":" stmts = Statements() { ret = new SwitchEntry(range(begin, token()), labels, STATEMENT_GROUP, stmts); }
+    |
+        "->"
+        (
+            expression = Expression() ";" {
+                TokenRange r=range(begin, token());
+				stmts.add(new ExpressionStmt(r, expression));
+				ret = new SwitchEntry(r, labels, EXPRESSION, stmts);
+            }
+		|
+			stmt = Block() {
+				TokenRange r=range(begin, token());
+				stmts.add(stmt);
+				ret = new SwitchEntry(r, labels, BLOCK, stmts);
+			}
+		|
+			stmt = ThrowStatement() {
+				TokenRange r=range(begin, token());
+				stmts.add(stmt);
+				ret = new SwitchEntry(r, labels, THROWS_STATEMENT, stmts);
+			}
+		)
+    )
+	{ return ret; }
 }
 
 IfStmt IfStatement():
@@ -2308,7 +2353,7 @@
 
   {
   	if (varExpr != null) {
-  		return new ForeachStmt(range(begin, token()),varExpr, expr, body);
+  		return new ForEachStmt(range(begin, token()),varExpr, expr, body);
   	}
 	return new ForStmt(range(begin, token()),init, expr, update, body);
   }
@@ -2352,12 +2397,12 @@
 
 BreakStmt BreakStatement():
 {
-	SimpleName label = null;
+	Expression value = null;
 	JavaToken begin;
 }
 {
-  "break" {begin=token();} [ label = SimpleName() ] ";"
-  { return new BreakStmt(range(begin, token()), label); }
+  "break" {begin=token();} [ value = Expression() ] ";"
+  { return new BreakStmt(range(begin, token()), value); }
 }
 
 ContinueStmt ContinueStatement():
@@ -2426,8 +2471,8 @@
         LOOKAHEAD(2)
   		(
   			"catch" {catchBegin=token();}
-  			"(" { typesBegin=token(); }
-  			exceptModifier = Modifiers() exceptionType = ReferenceType(emptyList()) { exceptionTypes.add(exceptionType); }
+  			"(" exceptModifier = Modifiers() { typesBegin = exceptModifier.begin; }
+            exceptionType = ReferenceType(emptyList()) { exceptionTypes.add(exceptionType); typesBegin = orIfInvalid(typesBegin, token()); }
   			( "|" exceptionType = AnnotatedReferenceType() { exceptionTypes.add(exceptionType); } )*
   			exceptId = VariableDeclaratorId() { paramEnd = token(); }
   			")"
@@ -2439,7 +2484,7 @@
   			    } else {
   			        type = (Type)exceptionTypes.get(0);
   			    }
-				Parameter catchType = new Parameter(range(type, paramEnd), exceptModifier.modifiers, exceptModifier.annotations, type, false, emptyList(), exceptId.a);
+				Parameter catchType = new Parameter(range(typesBegin, paramEnd), exceptModifier.modifiers, exceptModifier.annotations, type, false, emptyList(), exceptId.a);
   			    catchs = add(catchs, new CatchClause(range(catchBegin, token()), catchType, catchBlock));
   			    exceptionTypes = emptyList(); }
   		)*
@@ -2678,43 +2723,40 @@
 /* Module syntax follows */
 
 
-ModuleStmt ModuleStmt():
+ModuleDirective ModuleDirective():
 {
     ModifierHolder modifiers;
     Name name;
     Name tmpName;
     NodeList<Name> names=emptyList();
-    Type type;
-    Type tmpType;
-    NodeList<Type> types=emptyList();
     JavaToken begin;
-    ModuleStmt stmt=new ModuleRequiresStmt();
+    ModuleDirective directive;
     JavaToken transitiveExceptionalToken;
 }
 {
     (
         // This is a hack for the edge case "requires transitive;" which is supposed to mean "require the module named 'transitive'" 
         LOOKAHEAD(<REQUIRES> <TRANSITIVE> ";")
-        <REQUIRES> {begin=token();} <TRANSITIVE> {transitiveExceptionalToken=token(); setTokenKind(IDENTIFIER);} ";" {stmt=new ModuleRequiresStmt(range(begin, token()), EnumSet.noneOf(Modifier.class), new Name(range(transitiveExceptionalToken, transitiveExceptionalToken), null, transitiveExceptionalToken.getText(), new NodeList<AnnotationExpr>()));}
+        <REQUIRES> {begin=token();} <TRANSITIVE> {transitiveExceptionalToken=token(); setTokenKind(IDENTIFIER);} ";" {directive=new ModuleRequiresDirective(range(begin, token()), new NodeList<Modifier>(), new Name(range(transitiveExceptionalToken, transitiveExceptionalToken), null, transitiveExceptionalToken.getText()));}
     |
-        <REQUIRES> {begin=token();} modifiers=Modifiers() name=Name() ";" {stmt=new ModuleRequiresStmt(range(begin, token()), modifiers.modifiers, name);}
+        <REQUIRES> {begin=token();} modifiers=Modifiers() name=Name() ";" {directive=new ModuleRequiresDirective(range(begin, token()), modifiers.modifiers, name);}
     |
-        <EXPORTS> {begin=token();} name=Name() [<TO> tmpName=Name() {names.add(tmpName);} ("," tmpName=Name(){names.add(tmpName);} )* ] ";" {stmt=new ModuleExportsStmt(range(begin, token()), name, names);}
+        <EXPORTS> {begin=token();} name=Name() [<TO> tmpName=Name() {names.add(tmpName);} ("," tmpName=Name(){names.add(tmpName);} )* ] ";" {directive=new ModuleExportsDirective(range(begin, token()), name, names);}
     |
-        <OPENS> {begin=token();} name=Name() [<TO> tmpName=Name() {names.add(tmpName);} ("," tmpName=Name(){names.add(tmpName);} )* ] ";" {stmt=new ModuleOpensStmt(range(begin, token()), name, names);}
+        <OPENS> {begin=token();} name=Name() [<TO> tmpName=Name() {names.add(tmpName);} ("," tmpName=Name(){names.add(tmpName);} )* ] ";" {directive=new ModuleOpensDirective(range(begin, token()), name, names);}
     |
-        <USES> { begin=token();} type=Type(emptyList()) ";" {stmt=new ModuleUsesStmt(range(begin, token()), type);}
+        <USES> { begin=token();} name=Name() ";" {directive=new ModuleUsesDirective(range(begin, token()), name);}
     |
-        <PROVIDES> { begin=token();} type=Type(emptyList()) <WITH> tmpType=Type(emptyList()) {types.add(tmpType);} ("," tmpType=Type(emptyList()) {types.add(tmpType);}  )* ";" {stmt=new ModuleProvidesStmt(range(begin, token()), type, types);}
+        <PROVIDES> { begin=token();} name=Name() <WITH> tmpName=Name() {names.add(tmpName);} ("," tmpName=Name() {names.add(tmpName);}  )* ";" {directive=new ModuleProvidesDirective(range(begin, token()), name, names);}
     )
-    { return stmt; }
+    { return directive; }
 }
 
 ModuleDeclaration ModuleDeclaration(ModifierHolder modifier):
 {
-    NodeList<ModuleStmt> statements = new NodeList<ModuleStmt>();
+    NodeList<ModuleDirective> directives = new NodeList<ModuleDirective>();
     boolean open=false;
-    ModuleStmt st;
+    ModuleDirective directive;
     Name name;
     JavaToken begin = modifier.begin;
 }
@@ -2722,9 +2764,9 @@
     [ <OPEN> {open=true; begin = orIfInvalid(begin, token());} ]
     <MODULE> { begin = orIfInvalid(begin, token()); }
     name = Name() "{"
-    ( st = ModuleStmt() { statements = add(statements, st); } )*
+    ( directive = ModuleDirective() { directives = add(directives, directive); } )*
     "}"
-    { return new ModuleDeclaration(range(begin, token()), modifier.annotations, name, open, statements); }
+    { return new ModuleDeclaration(range(begin, token()), modifier.annotations, name, open, directives); }
 }
 
 /* Rules for matching partial inputs.
@@ -2793,3 +2835,44 @@
 PackageDeclaration PackageDeclarationParseStart():
 { PackageDeclaration ret; }
 { ret = PackageDeclaration() <EOF> { return ret; } }
+
+TypeDeclaration<?> TypeDeclarationParseStart():
+{
+	TypeDeclaration<?> ret;
+	ModifierHolder modifier;
+}
+{
+	modifier = Modifiers()
+	(ret = ClassOrInterfaceDeclaration(modifier)
+	|ret = EnumDeclaration(modifier)
+	|ret = AnnotationTypeDeclaration(modifier)
+	)
+	<EOF>
+	{return ret;}
+}
+
+ModuleDeclaration ModuleDeclarationParseStart():
+{
+	ModuleDeclaration ret;
+ 	ModifierHolder modifiers;
+}
+{
+	modifiers = Modifiers()
+	ret = ModuleDeclaration(modifiers)
+	<EOF>
+	{ return ret; }
+}
+
+ModuleDirective ModuleDirectiveParseStart():
+{ ModuleDirective ret; }
+{ ret = ModuleDirective() <EOF> { return ret; } }
+
+TypeParameter TypeParameterParseStart():
+{
+	TypeParameter ret;
+	NodeList<AnnotationExpr> annotations;
+}
+{
+   annotations = Annotations() ret = TypeParameter(annotations) <EOF>
+   { return ret; }
+}
diff --git a/javaparser-metamodel-generator/javaparser-metamodel-generator.iml b/javaparser-metamodel-generator/javaparser-metamodel-generator.iml
deleted file mode 100644
index 1f0ec62..0000000
--- a/javaparser-metamodel-generator/javaparser-metamodel-generator.iml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="javaparser-core" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-metamodel-generator/pom.xml b/javaparser-metamodel-generator/pom.xml
deleted file mode 100644
index 7a1e498..0000000
--- a/javaparser-metamodel-generator/pom.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?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.5.16-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>javaparser-metamodel-generator</artifactId>
-    <description>The tool that generates the code in the javaparser-metamodel module</description>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.github.javaparser</groupId>
-            <artifactId>javaparser-core</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <!-- no need to release this module -->
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>run-metamodel-generator</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>generate-javaparser-metamodel</id>
-                                <phase>test</phase>
-                                <goals>
-                                    <goal>java</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                        <configuration>
-                            <classpathScope>test</classpathScope>
-                            <mainClass>com.github.javaparser.generator.metamodel.MetaModelGenerator</mainClass>
-                            <arguments>
-                                <argument>${project.basedir}</argument>
-                            </arguments>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
diff --git a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/AstTypeAnalysis.java b/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/AstTypeAnalysis.java
deleted file mode 100644
index 1801f2d..0000000
--- a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/AstTypeAnalysis.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.github.javaparser.generator.metamodel;
-
-import com.github.javaparser.ast.NodeList;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.WildcardType;
-import java.util.EnumSet;
-import java.util.Optional;
-
-import static java.lang.reflect.Modifier.isAbstract;
-
-/**
- * A hacky thing that collects flags we need from AST types to generate the metamodel.
- */
-public class AstTypeAnalysis {
-    public final boolean isAbstract;
-    public boolean isOptional = false;
-    public boolean isEnumSet = false;
-    public boolean isNodeList = false;
-    public boolean isSelfType = false;
-    public Class<?> innerType;
-
-    AstTypeAnalysis(Type type) {
-        if (type instanceof Class<?>) {
-            TypeVariable<? extends Class<?>>[] typeParameters = ((Class<?>) type).getTypeParameters();
-            if (typeParameters.length > 0) {
-                isSelfType = true;
-            }
-        } else {
-            while (type instanceof ParameterizedType) {
-                ParameterizedType t = (ParameterizedType) type;
-                Type currentOuterType = t.getRawType();
-                if (currentOuterType == NodeList.class) {
-                    isNodeList = true;
-                }
-                if (currentOuterType == Optional.class) {
-                    isOptional = true;
-                }
-                if (currentOuterType == EnumSet.class) {
-                    isEnumSet = true;
-                }
-
-                if (t.getActualTypeArguments()[0] instanceof WildcardType) {
-                    type = t.getRawType();
-                    isSelfType = true;
-                    break;
-                }
-                type = t.getActualTypeArguments()[0];
-            }
-        }
-        innerType = (Class<?>) type;
-        isAbstract = isAbstract(innerType.getModifiers());
-    }
-}
diff --git a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializeConstructorParametersStatementsGenerator.java b/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializeConstructorParametersStatementsGenerator.java
deleted file mode 100644
index d50c0ed..0000000
--- a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializeConstructorParametersStatementsGenerator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.github.javaparser.generator.metamodel;
-
-import com.github.javaparser.ast.AllFieldsConstructor;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.stmt.Statement;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-
-import static com.github.javaparser.JavaParser.parseStatement;
-import static com.github.javaparser.generator.metamodel.MetaModelGenerator.nodeMetaModelFieldName;
-import static com.github.javaparser.generator.metamodel.MetaModelGenerator.propertyMetaModelFieldName;
-import static com.github.javaparser.utils.CodeGenerationUtils.f;
-
-class InitializeConstructorParametersStatementsGenerator {
-    void generate(Class<? extends Node> nodeClass, NodeList<Statement> initializeConstructorParametersStatements) {
-        if (nodeClass == Node.class) {
-            return;
-        }
-        Constructor<?> constructor = findAllFieldsConstructor(nodeClass);
-        for (java.lang.reflect.Parameter parameter : constructor.getParameters()) {
-            Field field = findFieldInClass(nodeClass, parameter.getName());
-
-            String addFieldStatement = f("%s.getConstructorParameters().add(%s.%s);",
-                    nodeMetaModelFieldName(nodeClass),
-                    nodeMetaModelFieldName(field.getDeclaringClass()),
-                    propertyMetaModelFieldName(field));
-
-            initializeConstructorParametersStatements.add(parseStatement(addFieldStatement));
-        }
-    }
-
-    private Field findFieldInClass(Class<?> nodeClass, String name) {
-        Class<?> searchClass = nodeClass;
-        do {
-            for (Field field : searchClass.getDeclaredFields()) {
-                if (field.getName().equals(name)) {
-                    return field;
-                }
-            }
-            searchClass = searchClass.getSuperclass();
-        } while (searchClass != null);
-        throw new AssertionError(f("Couldn't find constructor parameter %s as a field, class %s", name, nodeClass.getSimpleName()));
-    }
-
-    private Constructor<?> findAllFieldsConstructor(Class<? extends Node> nodeClass) {
-        for (Constructor<?> constructor : nodeClass.getDeclaredConstructors()) {
-            for (Annotation annotation : constructor.getAnnotations()) {
-                if (annotation.annotationType() == AllFieldsConstructor.class) {
-                    return constructor;
-                }
-            }
-        }
-        throw new AssertionError(f("Node class %s has no constructor annotated with @AllFieldsConstructor", nodeClass.getSimpleName()));
-    }
-}
diff --git a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializePropertyMetaModelsStatementsGenerator.java b/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializePropertyMetaModelsStatementsGenerator.java
deleted file mode 100644
index be1ff54..0000000
--- a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/InitializePropertyMetaModelsStatementsGenerator.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.github.javaparser.generator.metamodel;
-
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.metamodel.NonEmptyProperty;
-import com.github.javaparser.metamodel.OptionalProperty;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-import static com.github.javaparser.JavaParser.parseStatement;
-import static com.github.javaparser.ast.Modifier.PUBLIC;
-import static com.github.javaparser.generator.metamodel.MetaModelGenerator.isNode;
-import static com.github.javaparser.generator.metamodel.MetaModelGenerator.nodeMetaModelName;
-import static com.github.javaparser.utils.CodeGenerationUtils.*;
-import static com.github.javaparser.utils.Utils.decapitalize;
-
-class InitializePropertyMetaModelsStatementsGenerator {
-    void generate(Field field, ClassOrInterfaceDeclaration nodeMetaModelClass, String nodeMetaModelFieldName, NodeList<Statement> initializePropertyMetaModelsStatements) throws NoSuchMethodException {
-        final AstTypeAnalysis fieldTypeAnalysis = new AstTypeAnalysis(field.getGenericType());
-
-        final Class<?> fieldType = fieldTypeAnalysis.innerType;
-        final String typeName = fieldType.getTypeName().replace('$', '.');
-        final String propertyMetaModelFieldName = field.getName() + "PropertyMetaModel";
-        nodeMetaModelClass.addField("PropertyMetaModel", propertyMetaModelFieldName, PUBLIC);
-        final String propertyInitializer = f("new PropertyMetaModel(%s, \"%s\", %s.class, %s, %s, %s, %s, %s, %s)",
-                nodeMetaModelFieldName,
-                field.getName(),
-                typeName,
-                optionalOf(decapitalize(nodeMetaModelName(fieldType)), isNode(fieldType)),
-                isOptional(field),
-                isNonEmpty(field),
-                fieldTypeAnalysis.isNodeList,
-                fieldTypeAnalysis.isEnumSet,
-                fieldTypeAnalysis.isSelfType);
-        final String fieldSetting = f("%s.%s=%s;", nodeMetaModelFieldName, propertyMetaModelFieldName, propertyInitializer);
-        final String fieldAddition = f("%s.getDeclaredPropertyMetaModels().add(%s.%s);", nodeMetaModelFieldName, nodeMetaModelFieldName, propertyMetaModelFieldName);
-
-        initializePropertyMetaModelsStatements.add(parseStatement(fieldSetting));
-        initializePropertyMetaModelsStatements.add(parseStatement(fieldAddition));
-    }
-
-    void generateDerivedProperty(Method method, ClassOrInterfaceDeclaration nodeMetaModelClass, String nodeMetaModelFieldName, NodeList<Statement> initializePropertyMetaModelsStatements) {
-        final AstTypeAnalysis returnTypeAnalysis = new AstTypeAnalysis(method.getGenericReturnType());
-
-        final Class<?> innermostReturnType = returnTypeAnalysis.innerType;
-        final String typeName = innermostReturnType.getTypeName().replace('$', '.');
-        final String propertyMetaModelFieldName = getterToPropertyName(method.getName()) + "PropertyMetaModel";
-        nodeMetaModelClass.addField("PropertyMetaModel", propertyMetaModelFieldName, PUBLIC);
-        final String propertyInitializer = f("new PropertyMetaModel(%s, \"%s\", %s.class, %s, %s, %s, %s, %s, %s)",
-                nodeMetaModelFieldName,
-                getterToPropertyName(method.getName()),
-                typeName,
-                optionalOf(decapitalize(nodeMetaModelName(innermostReturnType)), isNode(innermostReturnType)),
-                returnTypeAnalysis.isOptional,
-                isNonEmpty(method),
-                returnTypeAnalysis.isNodeList,
-                returnTypeAnalysis.isEnumSet,
-                returnTypeAnalysis.isSelfType);
-        final String fieldSetting = f("%s.%s=%s;", nodeMetaModelFieldName, propertyMetaModelFieldName, propertyInitializer);
-        final String fieldAddition = f("%s.getDerivedPropertyMetaModels().add(%s.%s);", nodeMetaModelFieldName, nodeMetaModelFieldName, propertyMetaModelFieldName);
-
-        initializePropertyMetaModelsStatements.add(parseStatement(fieldSetting));
-        initializePropertyMetaModelsStatements.add(parseStatement(fieldAddition));
-    }
-
-    private boolean isNonEmpty(Field field) {
-        return field.isAnnotationPresent(NonEmptyProperty.class);
-    }
-
-    private boolean isNonEmpty(Method method) {
-        return method.isAnnotationPresent(NonEmptyProperty.class);
-    }
-
-    private boolean isOptional(Field field) {
-        return field.isAnnotationPresent(OptionalProperty.class);
-    }
-}
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
deleted file mode 100644
index 43d9112..0000000
--- a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/MetaModelGenerator.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package com.github.javaparser.generator.metamodel;
-
-import com.github.javaparser.ast.*;
-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.modules.*;
-import com.github.javaparser.ast.stmt.*;
-import com.github.javaparser.ast.type.*;
-import com.github.javaparser.printer.PrettyPrinter;
-import com.github.javaparser.printer.PrettyPrinterConfiguration;
-import com.github.javaparser.utils.SourceRoot;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-
-import static com.github.javaparser.utils.Utils.decapitalize;
-
-public class MetaModelGenerator {
-    static final String BASE_NODE_META_MODEL = "BaseNodeMetaModel";
-    private static List<Class<? extends Node>> ALL_NODE_CLASSES = new ArrayList<Class<? extends Node>>() {{
-        /* Base classes go first, so we don't have to do any sorting to make sure
-         generated classes can refer to their base generated classes without
-         being afraid those are not initialized yet. */
-        add(Node.class);
-
-        add(BodyDeclaration.class);
-        add(CallableDeclaration.class);
-        add(Statement.class);
-        add(Expression.class);
-        add(Type.class);
-
-        add(AnnotationExpr.class);
-        add(TypeDeclaration.class);
-        add(ReferenceType.class);
-
-        add(LiteralExpr.class);
-        add(LiteralStringValueExpr.class);
-        add(StringLiteralExpr.class);
-
-        add(ModuleDeclaration.class);
-        add(ModuleStmt.class);
-
-        //
-        add(ArrayCreationLevel.class);
-        add(CompilationUnit.class);
-        add(PackageDeclaration.class);
-
-        add(AnnotationDeclaration.class);
-        add(AnnotationMemberDeclaration.class);
-        add(ClassOrInterfaceDeclaration.class);
-        add(ConstructorDeclaration.class);
-        add(EnumConstantDeclaration.class);
-        add(EnumDeclaration.class);
-        add(FieldDeclaration.class);
-        add(InitializerDeclaration.class);
-        add(MethodDeclaration.class);
-        add(Parameter.class);
-        add(ReceiverParameter.class);
-        add(VariableDeclarator.class);
-
-        add(Comment.class);
-        add(BlockComment.class);
-        add(JavadocComment.class);
-        add(LineComment.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(FieldAccessExpr.class);
-        add(InstanceOfExpr.class);
-        add(IntegerLiteralExpr.class);
-        add(LambdaExpr.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(SuperExpr.class);
-        add(ThisExpr.class);
-        add(TypeExpr.class);
-        add(UnaryExpr.class);
-        add(VariableDeclarationExpr.class);
-
-        add(ImportDeclaration.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(SwitchEntryStmt.class);
-        add(SwitchStmt.class);
-        add(SynchronizedStmt.class);
-        add(ThrowStmt.class);
-        add(TryStmt.class);
-        add(LocalClassDeclarationStmt.class);
-        add(WhileStmt.class);
-        add(UnparsableStmt.class);
-
-        add(ArrayType.class);
-        add(ClassOrInterfaceType.class);
-        add(IntersectionType.class);
-        add(PrimitiveType.class);
-        add(TypeParameter.class);
-        add(UnionType.class);
-        add(UnknownType.class);
-        add(VoidType.class);
-        add(WildcardType.class);
-        add(VarType.class);
-
-        add(ModuleRequiresStmt.class);
-        add(ModuleExportsStmt.class);
-        add(ModuleProvidesStmt.class);
-        add(ModuleUsesStmt.class);
-        add(ModuleOpensStmt.class);
-    }};
-
-    static String METAMODEL_PACKAGE = "com.github.javaparser.metamodel";
-
-    public static void main(String[] args) throws IOException, NoSuchMethodException {
-        if (args.length != 1) {
-            throw new RuntimeException("Need 1 parameter: the JavaParser source checkout root directory.");
-        }
-        final Path root = Paths.get(args[0], "..", "javaparser-core", "src", "main", "java");
-        final SourceRoot sourceRoot = new SourceRoot(root);
-        sourceRoot.setPrinter(new PrettyPrinter(new PrettyPrinterConfiguration().setEndOfLineCharacter("\n"))::print);
-
-        new MetaModelGenerator().run(sourceRoot);
-
-        sourceRoot.saveAll();
-    }
-
-    private void run(SourceRoot sourceRoot) throws IOException, NoSuchMethodException {
-        final CompilationUnit javaParserMetaModel = sourceRoot.parse(METAMODEL_PACKAGE, "JavaParserMetaModel.java");
-
-        generateNodeMetaModels(javaParserMetaModel, sourceRoot);
-    }
-
-    private void generateNodeMetaModels(CompilationUnit javaParserMetaModelCu, SourceRoot sourceRoot) throws NoSuchMethodException {
-        final ClassOrInterfaceDeclaration metaModelCoid = javaParserMetaModelCu.getClassByName("JavaParserMetaModel").get();
-        final NodeList<Statement> initializeNodeMetaModelsStatements = metaModelCoid.getMethodsByName("initializeNodeMetaModels").get(0).getBody().get().getStatements();
-        final NodeList<Statement> initializePropertyMetaModelsStatements = metaModelCoid.getMethodsByName("initializePropertyMetaModels").get(0).getBody().get().getStatements();
-        final NodeList<Statement> initializeConstructorParametersStatements = metaModelCoid.getMethodsByName("initializeConstructorParameters").get(0).getBody().get().getStatements();
-        initializeNodeMetaModelsStatements.clear();
-        initializePropertyMetaModelsStatements.clear();
-        initializeConstructorParametersStatements.clear();
-
-        metaModelCoid.getFields().stream().filter(f -> f.getVariable(0).getNameAsString().endsWith("MetaModel")).forEach(Node::remove);
-        final NodeMetaModelGenerator nodeMetaModelGenerator = new NodeMetaModelGenerator();
-        for (Class<? extends Node> nodeClass : ALL_NODE_CLASSES) {
-            nodeMetaModelGenerator.generate(nodeClass, metaModelCoid, initializeNodeMetaModelsStatements, initializePropertyMetaModelsStatements, initializeConstructorParametersStatements, sourceRoot);
-        }
-
-        initializeNodeMetaModelsStatements.sort(Comparator.comparing(Node::toString));
-    }
-
-    static boolean isNode(Class<?> c) {
-        return Node.class.isAssignableFrom(c);
-    }
-
-    static String nodeMetaModelName(Class<?> c) {
-        return c.getSimpleName() + "MetaModel";
-    }
-
-    static String propertyMetaModelFieldName(Field field) {
-        return field.getName() + "PropertyMetaModel";
-    }
-
-    static String nodeMetaModelFieldName(Class<?> nodeClass) {
-        return decapitalize(nodeMetaModelName(nodeClass));
-    }
-
-}
diff --git a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/NodeMetaModelGenerator.java b/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/NodeMetaModelGenerator.java
deleted file mode 100644
index 96f92ab..0000000
--- a/javaparser-metamodel-generator/src/main/java/com/github/javaparser/generator/metamodel/NodeMetaModelGenerator.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.github.javaparser.generator.metamodel;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.metamodel.DerivedProperty;
-import com.github.javaparser.metamodel.InternalProperty;
-import com.github.javaparser.utils.SourceRoot;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-
-import static com.github.javaparser.JavaParser.*;
-import static com.github.javaparser.ast.Modifier.*;
-import static com.github.javaparser.generator.metamodel.MetaModelGenerator.*;
-import static com.github.javaparser.utils.CodeGenerationUtils.f;
-import static com.github.javaparser.utils.CodeGenerationUtils.optionalOf;
-import static com.github.javaparser.utils.Utils.decapitalize;
-
-public class NodeMetaModelGenerator {
-    private final InitializePropertyMetaModelsStatementsGenerator initializePropertyMetaModelsStatementsGenerator = new InitializePropertyMetaModelsStatementsGenerator();
-    private final InitializeConstructorParametersStatementsGenerator initializeConstructorParametersStatementsGenerator = new InitializeConstructorParametersStatementsGenerator();
-
-    public void generate(Class<? extends Node> nodeClass, ClassOrInterfaceDeclaration metaModelCoid, NodeList<Statement> initializeNodeMetaModelsStatements, NodeList<Statement> initializePropertyMetaModelsStatements, NodeList<Statement> initializeConstructorParametersStatements, SourceRoot sourceRoot) throws NoSuchMethodException {
-        final String className = nodeMetaModelName(nodeClass);
-        final String nodeMetaModelFieldName = decapitalize(className);
-        metaModelCoid.getFieldByName(nodeMetaModelFieldName).ifPresent(Node::remove);
-
-        final FieldDeclaration nodeField = metaModelCoid.addField(className, nodeMetaModelFieldName, PUBLIC, STATIC, FINAL);
-
-        final Class<?> superclass = nodeClass.getSuperclass();
-        final String superNodeMetaModel = nodeMetaModelName(superclass);
-
-        boolean isRootNode = !isNode(superclass);
-        nodeField.getVariable(0).setInitializer(parseExpression(f("new %s(%s)",
-                className,
-                optionalOf(decapitalize(superNodeMetaModel), !isRootNode))));
-
-        initializeNodeMetaModelsStatements.add(parseStatement(f("nodeMetaModels.add(%s);", nodeMetaModelFieldName)));
-
-        final CompilationUnit classMetaModelJavaFile = new CompilationUnit(METAMODEL_PACKAGE);
-        classMetaModelJavaFile.addImport("java.util.Optional");
-        sourceRoot.add(METAMODEL_PACKAGE, className + ".java", classMetaModelJavaFile);
-        final ClassOrInterfaceDeclaration nodeMetaModelClass = classMetaModelJavaFile.addClass(className, PUBLIC);
-        if (isRootNode) {
-            nodeMetaModelClass.addExtendedType(BASE_NODE_META_MODEL);
-        } else {
-            nodeMetaModelClass.addExtendedType(superNodeMetaModel);
-        }
-
-        final AstTypeAnalysis typeAnalysis = new AstTypeAnalysis(nodeClass);
-
-        final ConstructorDeclaration classMMConstructor = nodeMetaModelClass
-                .addConstructor()
-                .addParameter("Optional<" + BASE_NODE_META_MODEL + ">", "super" + BASE_NODE_META_MODEL);
-        classMMConstructor
-                .getBody()
-                .addStatement(parseExplicitConstructorInvocationStmt(f("super(super%s, %s.class, \"%s\", \"%s\", %s, %s);",
-                        BASE_NODE_META_MODEL,
-                        nodeClass.getName(),
-                        nodeClass.getSimpleName(),
-                        nodeClass.getPackage().getName(),
-                        typeAnalysis.isAbstract,
-                        typeAnalysis.isSelfType)));
-
-        if (typeAnalysis.isAbstract) {
-            classMetaModelJavaFile.addImport(Node.class);
-            nodeMetaModelClass.addMember(parseBodyDeclaration(f(
-                    "protected %s(Optional<BaseNodeMetaModel> superNodeMetaModel, Class<? extends Node> type, String name, String packageName, boolean isAbstract, boolean hasWildcard) {" +
-                            "super(superNodeMetaModel, type, name, packageName, isAbstract, hasWildcard);" +
-                            " }",
-                    className)));
-        }
-
-        final List<Field> fields = new ArrayList<>(Arrays.asList(nodeClass.getDeclaredFields()));
-        fields.sort(Comparator.comparing(Field::getName));
-        for (Field field : fields) {
-            if (fieldShouldBeIgnored(field)) {
-                continue;
-            }
-
-            initializePropertyMetaModelsStatementsGenerator.generate(field, nodeMetaModelClass, nodeMetaModelFieldName, initializePropertyMetaModelsStatements);
-        }
-        final List<Method> methods = new ArrayList<>(Arrays.asList(nodeClass.getMethods()));
-        methods.sort(Comparator.comparing(Method::getName));
-        for (Method method : methods) {
-            if (method.isAnnotationPresent(DerivedProperty.class)) {
-                initializePropertyMetaModelsStatementsGenerator.generateDerivedProperty(method, nodeMetaModelClass, nodeMetaModelFieldName, initializePropertyMetaModelsStatements);
-            }
-        }
-
-        initializeConstructorParametersStatementsGenerator.generate(nodeClass, initializeConstructorParametersStatements);
-
-        moveStaticInitializeToTheEndOfTheClassBecauseWeNeedTheFieldsToInitializeFirst(metaModelCoid);
-    }
-
-    private void moveStaticInitializeToTheEndOfTheClassBecauseWeNeedTheFieldsToInitializeFirst(ClassOrInterfaceDeclaration metaModelCoid) {
-        for (BodyDeclaration<?> m : metaModelCoid.getMembers()) {
-            if (m instanceof InitializerDeclaration) {
-                m.remove();
-                metaModelCoid.addMember(m);
-                return;
-            }
-        }
-    }
-
-    private boolean fieldShouldBeIgnored(Field reflectionField) {
-        return java.lang.reflect.Modifier.isStatic(reflectionField.getModifiers()) ||
-                reflectionField.isAnnotationPresent(InternalProperty.class);
-    }
-}
diff --git a/javaparser-parent.iml b/javaparser-parent.iml
deleted file mode 100644
index 880f417..0000000
--- a/javaparser-parent.iml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="FacetManager">
-    <facet type="Osmorc" name="OSGi">
-      <configuration manifestGenerationMode="Manually" manifestLocation="javaparser-bdd-testing/target/classes/META-INF/MANIFEST.MF" jarfileLocation="javaparser-parent.jar" outputPathType="CompilerOutputPath" bndFileLocation="" bundlorFileLocation="" bundleActivator="" bundleSymbolicName="" bundleVersion="1.0.0" ignoreFilePattern="" useProjectDefaultManifestFileLocation="false" alwaysRebuildBundleJAR="false" doNotSynchronizeWithMaven="false">
-        <additionalProperties />
-        <additionalJARContents />
-      </configuration>
-    </facet>
-  </component>
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-symbol-solver-core/javaparser-symbol-solver-core.iml b/javaparser-symbol-solver-core/javaparser-symbol-solver-core.iml
deleted file mode 100644
index b1e3807..0000000
--- a/javaparser-symbol-solver-core/javaparser-symbol-solver-core.iml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="javaparser-symbol-solver-logic" />
-    <orderEntry type="library" name="Maven: org.javassist:javassist:3.22.0-GA" level="project" />
-    <orderEntry type="module" module-name="javaparser-symbol-solver-model" />
-    <orderEntry type="module" module-name="javaparser-core" />
-    <orderEntry type="library" name="Maven: com.google.guava:guava:23.4-jre" level="project" />
-    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
-    <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.0.18" level="project" />
-    <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.1" level="project" />
-    <orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14" level="project" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-symbol-solver-core/pom.xml b/javaparser-symbol-solver-core/pom.xml
index 97ff664..b2cb35a 100644
--- a/javaparser-symbol-solver-core/pom.xml
+++ b/javaparser-symbol-solver-core/pom.xml
@@ -3,7 +3,7 @@
   <parent>
       <artifactId>javaparser-parent</artifactId>
       <groupId>com.github.javaparser</groupId>
-      <version>3.5.16-SNAPSHOT</version>
+      <version>3.14.10-SNAPSHOT</version>
   </parent>    
   <modelVersion>4.0.0</modelVersion>
 
@@ -53,59 +53,6 @@
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>animal-sniffer-maven-plugin</artifactId>
-                <configuration>
-                    <signature>
-                        <!-- Make sure only the API of this JDK is used -->
-                        <groupId>org.codehaus.mojo.signature</groupId>
-                        <artifactId>java18</artifactId>
-                        <version>1.0</version>
-                    </signature>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>animal-sniffer</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>check</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-enforcer-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>enforce-versions</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>enforce</goal>
-                        </goals>
-                        <configuration>
-                            <rules>
-                                <requireJavaVersion>
-                                    <!-- Make sure a compiler of this version is used -->
-                                    <version>${java.version}</version>
-                                </requireJavaVersion>
-                                <enforceBytecodeVersion>
-                                    <!-- Make sure the dependencies are compiled for our Java version -->
-                                    <maxJdkVersion>${java.version}</maxJdkVersion>
-                                </enforceBytecodeVersion>
-                            </rules>
-                        </configuration>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>extra-enforcer-rules</artifactId>
-                        <version>1.0-beta-6</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
             <!-- Set JPMS module name -->
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java
index 77550c7..c26f1b4 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/JavaSymbolSolver.java
@@ -3,15 +3,13 @@
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.ThisExpr;
+import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.resolution.SymbolResolver;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.*;
+import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
@@ -20,16 +18,37 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
 /**
- * This implementation of the SymbolResolver wraps the functionalities of the library to make them easily usable
+ * This implementation of the SymbolResolver wraps the functionality of the library to make them easily usable
  * from JavaParser nodes.
- *
+ * <p>
  * An instance of this class should be created once and then injected in all the CompilationUnit for which we
- * want to enable symbol resolution. To do so the method inject can be used.
+ * want to enable symbol resolution. To do so the method inject can be used, or you can use
+ * {@link com.github.javaparser.ParserConfiguration#setSymbolResolver(SymbolResolver)} and the parser will do the
+ * injection for you.
  *
  * @author Federico Tomassetti
  */
 public class JavaSymbolSolver implements SymbolResolver {
 
+    private static class ArrayLengthValueDeclaration implements ResolvedValueDeclaration {
+
+        private static final ArrayLengthValueDeclaration INSTANCE = new ArrayLengthValueDeclaration();
+
+        private ArrayLengthValueDeclaration() {
+
+        }
+
+        @Override
+        public String getName() {
+            return "length";
+        }
+
+        @Override
+        public ResolvedType getType() {
+            return ResolvedPrimitiveType.INT;
+        }
+    }
+
     private TypeSolver typeSolver;
 
     public JavaSymbolSolver(TypeSolver typeSolver) {
@@ -47,7 +66,7 @@
     @Override
     public <T> T resolveDeclaration(Node node, Class<T> resultClass) {
         if (node instanceof MethodDeclaration) {
-            return resultClass.cast(new JavaParserMethodDeclaration((MethodDeclaration)node, typeSolver));
+            return resultClass.cast(new JavaParserMethodDeclaration((MethodDeclaration) node, typeSolver));
         }
         if (node instanceof ClassOrInterfaceDeclaration) {
             ResolvedReferenceTypeDeclaration resolved = JavaParserFactory.toTypeDeclaration(node, typeSolver);
@@ -62,17 +81,21 @@
             }
         }
         if (node instanceof EnumConstantDeclaration) {
-            ResolvedEnumDeclaration enumDeclaration = node.findParent(EnumDeclaration.class).get().resolve().asEnum();
-            ResolvedEnumConstantDeclaration resolved = enumDeclaration.getEnumConstants().stream().filter(c -> ((JavaParserEnumConstantDeclaration)c).getWrappedNode() == node).findFirst().get();
+            ResolvedEnumDeclaration enumDeclaration = node.findAncestor(EnumDeclaration.class).get().resolve().asEnum();
+            ResolvedEnumConstantDeclaration resolved = enumDeclaration.getEnumConstants().stream().filter(c -> ((JavaParserEnumConstantDeclaration) c).getWrappedNode() == node).findFirst().get();
             if (resultClass.isInstance(resolved)) {
                 return resultClass.cast(resolved);
             }
         }
         if (node instanceof ConstructorDeclaration) {
-            ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)node;
-            ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration)node.getParentNode().get();
-            ResolvedClassDeclaration resolvedClass = resolveDeclaration(classOrInterfaceDeclaration, ResolvedClassDeclaration.class).asClass();
-            ResolvedConstructorDeclaration resolved =  resolvedClass.getConstructors().stream().filter(c -> ((JavaParserConstructorDeclaration)c).getWrappedNode() == constructorDeclaration).findFirst().get();
+            ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) node;
+            TypeDeclaration<?> typeDeclaration = (TypeDeclaration<?>) node.getParentNode().get();
+            ResolvedReferenceTypeDeclaration resolvedTypeDeclaration = resolveDeclaration(typeDeclaration, ResolvedReferenceTypeDeclaration.class);
+            ResolvedConstructorDeclaration resolved = resolvedTypeDeclaration.getConstructors().stream()
+                    .filter(c -> c instanceof JavaParserConstructorDeclaration)
+                    .filter(c -> ((JavaParserConstructorDeclaration) c).getWrappedNode() == constructorDeclaration)
+                    .findFirst()
+                    .orElseThrow(() -> new RuntimeException("This constructor cannot be found in its parent. This seems wrong"));
             if (resultClass.isInstance(resolved)) {
                 return resultClass.cast(resolved);
             }
@@ -84,14 +107,14 @@
             }
         }
         if (node instanceof AnnotationMemberDeclaration) {
-            ResolvedAnnotationDeclaration annotationDeclaration = node.findParent(AnnotationDeclaration.class).get().resolve();
-            ResolvedAnnotationMemberDeclaration resolved = annotationDeclaration.getAnnotationMembers().stream().filter(c -> ((JavaParserAnnotationMemberDeclaration)c).getWrappedNode() == node).findFirst().get();
+            ResolvedAnnotationDeclaration annotationDeclaration = node.findAncestor(AnnotationDeclaration.class).get().resolve();
+            ResolvedAnnotationMemberDeclaration resolved = annotationDeclaration.getAnnotationMembers().stream().filter(c -> ((JavaParserAnnotationMemberDeclaration) c).getWrappedNode() == node).findFirst().get();
             if (resultClass.isInstance(resolved)) {
                 return resultClass.cast(resolved);
             }
         }
         if (node instanceof FieldDeclaration) {
-            FieldDeclaration fieldDeclaration = (FieldDeclaration)node;
+            FieldDeclaration fieldDeclaration = (FieldDeclaration) node;
             if (fieldDeclaration.getVariables().size() != 1) {
                 throw new RuntimeException("Cannot resolve a Field Declaration including multiple variable declarators. Resolve the single variable declarators");
             }
@@ -101,13 +124,20 @@
             }
         }
         if (node instanceof VariableDeclarator) {
-            ResolvedFieldDeclaration resolved = new JavaParserFieldDeclaration((VariableDeclarator)node, typeSolver);
+            ResolvedValueDeclaration resolved;
+            if (node.getParentNode().isPresent() && node.getParentNode().get() instanceof FieldDeclaration) {
+                resolved = new JavaParserFieldDeclaration((VariableDeclarator) node, typeSolver);
+            } else if (node.getParentNode().isPresent() && node.getParentNode().get() instanceof VariableDeclarationExpr) {
+                resolved = new JavaParserVariableDeclaration((VariableDeclarator) node, typeSolver);
+            } else {
+                throw new UnsupportedOperationException("Parent of VariableDeclarator is: " + node.getParentNode());
+            }
             if (resultClass.isInstance(resolved)) {
                 return resultClass.cast(resolved);
             }
         }
         if (node instanceof MethodCallExpr) {
-            SymbolReference<ResolvedMethodDeclaration> result = JavaParserFacade.get(typeSolver).solve((MethodCallExpr)node);
+            SymbolReference<ResolvedMethodDeclaration> result = JavaParserFacade.get(typeSolver).solve((MethodCallExpr) node);
             if (result.isSolved()) {
                 if (resultClass.isInstance(result.getCorrespondingDeclaration())) {
                     return resultClass.cast(result.getCorrespondingDeclaration());
@@ -116,6 +146,16 @@
                 throw new UnsolvedSymbolException("We are unable to find the method declaration corresponding to " + node);
             }
         }
+        if (node instanceof ObjectCreationExpr) {
+            SymbolReference<ResolvedConstructorDeclaration> result = JavaParserFacade.get(typeSolver).solve((ObjectCreationExpr) node);
+            if (result.isSolved()) {
+                if (resultClass.isInstance(result.getCorrespondingDeclaration())) {
+                    return resultClass.cast(result.getCorrespondingDeclaration());
+                }
+            } else {
+                throw new UnsolvedSymbolException("We are unable to find the constructor declaration corresponding to " + node);
+            }
+        }
         if (node instanceof NameExpr) {
             SymbolReference<? extends ResolvedValueDeclaration> result = JavaParserFacade.get(typeSolver).solve((NameExpr) node);
             if (result.isSolved()) {
@@ -126,6 +166,24 @@
                 throw new UnsolvedSymbolException("We are unable to find the value declaration corresponding to " + node);
             }
         }
+        if (node instanceof FieldAccessExpr) {
+            SymbolReference<? extends ResolvedValueDeclaration> result = JavaParserFacade.get(typeSolver).solve((FieldAccessExpr) node);
+            if (result.isSolved()) {
+                if (resultClass.isInstance(result.getCorrespondingDeclaration())) {
+                    return resultClass.cast(result.getCorrespondingDeclaration());
+                }
+            } else {
+                if (((FieldAccessExpr) node).getName().getId().equals("length")) {
+                    ResolvedType scopeType = ((FieldAccessExpr) node).getScope().calculateResolvedType();
+                    if (scopeType.isArray()) {
+                        if (resultClass.isInstance(ArrayLengthValueDeclaration.INSTANCE)) {
+                            return resultClass.cast(ArrayLengthValueDeclaration.INSTANCE);
+                        }
+                    }
+                }
+                throw new UnsolvedSymbolException("We are unable to find the value declaration corresponding to " + node);
+            }
+        }
         if (node instanceof ThisExpr) {
             SymbolReference<ResolvedTypeDeclaration> result = JavaParserFacade.get(typeSolver).solve((ThisExpr) node);
             if (result.isSolved()) {
@@ -148,21 +206,31 @@
         }
         if (node instanceof Parameter) {
             if (ResolvedParameterDeclaration.class.equals(resultClass)) {
-                Parameter parameter = (Parameter)node;
-                CallableDeclaration callableDeclaration = node.findParent(CallableDeclaration.class).get();
+                Parameter parameter = (Parameter) node;
+                CallableDeclaration callableDeclaration = node.findAncestor(CallableDeclaration.class).get();
                 ResolvedMethodLikeDeclaration resolvedMethodLikeDeclaration;
                 if (callableDeclaration.isConstructorDeclaration()) {
                     resolvedMethodLikeDeclaration = callableDeclaration.asConstructorDeclaration().resolve();
                 } else {
                     resolvedMethodLikeDeclaration = callableDeclaration.asMethodDeclaration().resolve();
                 }
-                for (int i=0;i<resolvedMethodLikeDeclaration.getNumberOfParams();i++) {
+                for (int i = 0; i < resolvedMethodLikeDeclaration.getNumberOfParams(); i++) {
                     if (resolvedMethodLikeDeclaration.getParam(i).getName().equals(parameter.getNameAsString())) {
                         return resultClass.cast(resolvedMethodLikeDeclaration.getParam(i));
                     }
                 }
             }
         }
+        if (node instanceof AnnotationExpr) {
+            SymbolReference<ResolvedAnnotationDeclaration> result = JavaParserFacade.get(typeSolver).solve((AnnotationExpr) node);
+            if (result.isSolved()) {
+                if (resultClass.isInstance(result.getCorrespondingDeclaration())) {
+                    return resultClass.cast(result.getCorrespondingDeclaration());
+                }
+            } else {
+                throw new UnsolvedSymbolException("We are unable to find the annotation declaration corresponding to " + node);
+            }
+        }
         throw new UnsupportedOperationException("Unable to find the declaration of type " + resultClass.getSimpleName()
                 + " from " + node.getClass().getSimpleName());
     }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java
index 8d2c07b..85d55f7 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java
@@ -16,9 +16,8 @@
 
 package com.github.javaparser.symbolsolver;
 
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.ImportDeclaration;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.PackageDeclaration;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
@@ -26,8 +25,8 @@
 import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.ImportDeclaration;
 import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.stmt.SwitchEntry;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
@@ -36,47 +35,50 @@
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.util.LinkedList;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
 import java.util.List;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+import static com.github.javaparser.StaticJavaParser.parse;
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
+import static java.util.Comparator.comparing;
 
 /**
- * It prints information extracted from a source file. It is mainly intended as an example usage of JavaSymbolSolver.
+ * Resolves resolvable nodes from one or more source files, and reports the results.
+ * It is mainly intended as an example usage of JavaSymbolSolver.
  *
  * @author Federico Tomassetti
  */
 public class SourceFileInfoExtractor {
 
-    private TypeSolver typeSolver;
+    private final TypeSolver typeSolver;
 
-    private int ok = 0;
-    private int ko = 0;
+    private int successes = 0;
+    private int failures = 0;
     private int unsupported = 0;
     private boolean printFileName = true;
     private PrintStream out = System.out;
     private PrintStream err = System.err;
+    private boolean verbose = false;
+
+    public SourceFileInfoExtractor(TypeSolver typeSolver) {
+        this.typeSolver = typeSolver;
+    }
 
     public void setVerbose(boolean verbose) {
         this.verbose = verbose;
     }
 
-    private boolean verbose = false;
-
     public void setPrintFileName(boolean printFileName) {
         this.printFileName = printFileName;
     }
 
-    public void clear() {
-        ok = 0;
-        ko = 0;
-        unsupported = 0;
-    }
-
     public void setOut(PrintStream out) {
         this.out = out;
     }
@@ -85,17 +87,16 @@
         this.err = err;
     }
 
-    public int getOk() {
-        return ok;
-
+    public int getSuccesses() {
+        return successes;
     }
 
     public int getUnsupported() {
         return unsupported;
     }
 
-    public int getKo() {
-        return ko;
+    public int getFailures() {
+        return failures;
     }
 
     private void solveTypeDecl(ClassOrInterfaceDeclaration node) {
@@ -115,21 +116,27 @@
         if (node instanceof ClassOrInterfaceDeclaration) {
             solveTypeDecl((ClassOrInterfaceDeclaration) node);
         } else if (node instanceof Expression) {
-            if ((requireParentNode(node) instanceof ImportDeclaration) || (requireParentNode(node) instanceof Expression)
-                    || (requireParentNode(node) instanceof MethodDeclaration)
-                    || (requireParentNode(node) instanceof PackageDeclaration)) {
+            Node parentNode = requireParentNode(node);
+            if (parentNode instanceof ImportDeclaration ||
+                    parentNode instanceof Expression ||
+                    parentNode instanceof MethodDeclaration ||
+                    parentNode instanceof PackageDeclaration) {
                 // skip
-            } else if ((requireParentNode(node) instanceof Statement) || (requireParentNode(node) instanceof VariableDeclarator)) {
+                return;
+            }
+            if (parentNode instanceof Statement ||
+                    parentNode instanceof VariableDeclarator ||
+                    parentNode instanceof SwitchEntry) {
                 try {
                     ResolvedType ref = JavaParserFacade.get(typeSolver).getType(node);
-                    out.println("  Line " + node.getRange().get().begin.line + ") " + node + " ==> " + ref.describe());
-                    ok++;
+                    out.println("  Line " + lineNr(node) + ") " + node + " ==> " + ref.describe());
+                    successes++;
                 } catch (UnsupportedOperationException upe) {
                     unsupported++;
                     err.println(upe.getMessage());
                     throw upe;
                 } catch (RuntimeException re) {
-                    ko++;
+                    failures++;
                     err.println(re.getMessage());
                     throw re;
                 }
@@ -139,7 +146,7 @@
 
     private void solveMethodCalls(Node node) {
         if (node instanceof MethodCallExpr) {
-            out.println("  Line " + node.getBegin().get().line + ") " + node + " ==> " + toString((MethodCallExpr) node));
+            out.println("  Line " + lineNr(node) + ") " + node + " ==> " + toString((MethodCallExpr) node));
         }
         for (Node child : node.getChildNodes()) {
             solveMethodCalls(child);
@@ -151,7 +158,7 @@
             return toString(JavaParserFacade.get(typeSolver).solve(node));
         } catch (Exception e) {
             if (verbose) {
-                System.err.println("Error resolving call at L" + node.getBegin().get().line + ": " + node);
+                System.err.println("Error resolving call at L" + lineNr(node) + ": " + node);
                 e.printStackTrace();
             }
             return "ERROR";
@@ -167,52 +174,46 @@
     }
 
     private List<Node> collectAllNodes(Node node) {
-        List<Node> nodes = new LinkedList<>();
-        collectAllNodes(node, nodes);
-        nodes.sort((n1, n2) -> n1.getBegin().get().compareTo(n2.getBegin().get()));
+        List<Node> nodes = new ArrayList<>();
+        node.walk(nodes::add);
+        nodes.sort(comparing(n -> n.getBegin().get()));
         return nodes;
     }
 
-    private void collectAllNodes(Node node, List<Node> nodes) {
-        nodes.add(node);
-        node.getChildNodes().forEach(c -> collectAllNodes(c, nodes));
-    }
-
-    public void solve(File file) throws IOException, ParseException {
-        if (file.isDirectory()) {
-            for (File f : file.listFiles()) {
-                solve(f);
-            }
-        } else {
-            if (file.getName().endsWith(".java")) {
-                if (printFileName) {
-                    out.println("- parsing " + file.getAbsolutePath());
+    public void solve(Path path) throws IOException {
+        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                if (file.toString().endsWith(".java")) {
+                    if (printFileName) {
+                        out.println("- parsing " + file.toAbsolutePath());
+                    }
+                    CompilationUnit cu = parse(file);
+                    List<Node> nodes = collectAllNodes(cu);
+                    nodes.forEach(n -> solve(n));
                 }
-                CompilationUnit cu = JavaParser.parse(file);
-                List<Node> nodes = collectAllNodes(cu);
-                nodes.forEach(n -> solve(n));
+                return FileVisitResult.CONTINUE;
             }
-        }
+        });
     }
 
-    public void solveMethodCalls(File file) throws IOException, ParseException {
-        if (file.isDirectory()) {
-            for (File f : file.listFiles()) {
-                solveMethodCalls(f);
-            }
-        } else {
-            if (file.getName().endsWith(".java")) {
-                if (printFileName) {
-                    out.println("- parsing " + file.getAbsolutePath());
+    public void solveMethodCalls(Path path) throws IOException {
+        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                if (file.toString().endsWith(".java")) {
+                    if (printFileName) {
+                        out.println("- parsing " + file.toAbsolutePath());
+                    }
+                    CompilationUnit cu = parse(file);
+                    solveMethodCalls(cu);
                 }
-                CompilationUnit cu = JavaParser.parse(file);
-                solveMethodCalls(cu);
+                return FileVisitResult.CONTINUE;
             }
-        }
+        });
     }
 
-    public void setTypeSolver(TypeSolver typeSolver) {
-        this.typeSolver = typeSolver;
+    private int lineNr(Node node) {
+        return node.getRange().map(range -> range.begin.line).orElseThrow(IllegalStateException::new);
     }
-
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/Context.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/Context.java
index 93b754b..a892d8a 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/Context.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/Context.java
@@ -16,13 +16,17 @@
 
 package com.github.javaparser.symbolsolver.core.resolution;
 
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.contexts.AbstractJavaParserContext;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.resolution.Value;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
@@ -38,25 +42,27 @@
 
     /* Type resolution */
 
-    default Optional<ResolvedType> solveGenericType(String name, TypeSolver typeSolver) {
+    default Optional<ResolvedType> solveGenericType(String name) {
         return Optional.empty();
     }
 
-    default SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    default SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
         Context parent = getParent();
         if (parent == null) {
             return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
         } else {
-            return parent.solveType(name, typeSolver);
+            return parent.solveType(name);
         }
     }
 
     /* Symbol resolution */
 
-    SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver);
+    default SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
+        return getParent().solveSymbol(name);
+    }
 
-    default Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
-        SymbolReference<? extends ResolvedValueDeclaration> ref = solveSymbol(name, typeSolver);
+    default Optional<Value> solveSymbolAsValue(String name) {
+        SymbolReference<? extends ResolvedValueDeclaration> ref = solveSymbol(name);
         if (ref.isSolved()) {
             Value value = Value.from(ref.getCorrespondingDeclaration());
             return Optional.of(value);
@@ -65,12 +71,100 @@
         }
     }
 
+    /**
+     * The local variables that are declared in this immediate context and made visible to a given child.
+     * This list could include values which are shadowed.
+     */
+    default List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        return Collections.emptyList();
+    }
+
+    /**
+     * The parameters that are declared in this immediate context and made visible to a given child.
+     * This list could include values which are shadowed.
+     */
+    default List<Parameter> parametersExposedToChild(Node child) {
+        return Collections.emptyList();
+    }
+
+    /**
+     * The fields that are declared and in this immediate context made visible to a given child.
+     * This list could include values which are shadowed.
+     */
+    default List<ResolvedFieldDeclaration> fieldsExposedToChild(Node child) {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Aim to resolve the given name by looking for a variable matching it.
+     *
+     * To do it consider local variables that are visible in a certain scope as defined in JLS 6.3. Scope of a Declaration.
+     *
+     * 1. The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration
+     * appears, starting with its own initializer and including any further declarators to the right in the local
+     * variable declaration statement.
+     *
+     * 2. The scope of a local variable declared in the ForInit part of a basic for statement (§14.14.1) includes all
+     * of the following:
+     * 2.1 Its own initializer
+     * 2.2 Any further declarators to the right in the ForInit part of the for statement
+     * 2.3 The Expression and ForUpdate parts of the for statement
+     * 2.4 The contained Statement
+     *
+     * 3. The scope of a local variable declared in the FormalParameter part of an enhanced for statement (§14.14.2) is
+     * the contained Statement.
+     * 4. The scope of a parameter of an exception handler that is declared in a catch clause of a try statement
+     * (§14.20) is the entire block associated with the catch.
+     *
+     * 5. The scope of a variable declared in the ResourceSpecification of a try-with-resources statement (§14.20.3) is
+     * from the declaration rightward over the remainder of the ResourceSpecification and the entire try block
+     * associated with the try-with-resources statement.
+     */
+    default Optional<VariableDeclarator> localVariableDeclarationInScope(String name) {
+        if (getParent() == null) {
+            return Optional.empty();
+        }
+        Optional<VariableDeclarator> localRes = getParent().localVariablesExposedToChild(((AbstractJavaParserContext)this)
+                .getWrappedNode()).stream().filter(vd -> vd.getNameAsString().equals(name)).findFirst();
+        if (localRes.isPresent()) {
+            return localRes;
+        }
+
+        return getParent().localVariableDeclarationInScope(name);
+    }
+
+    default Optional<Parameter> parameterDeclarationInScope(String name) {
+        if (getParent() == null) {
+            return Optional.empty();
+        }
+        Optional<Parameter> localRes = getParent().parametersExposedToChild(((AbstractJavaParserContext)this)
+                .getWrappedNode()).stream().filter(vd -> vd.getNameAsString().equals(name)).findFirst();
+        if (localRes.isPresent()) {
+            return localRes;
+        }
+
+        return getParent().parameterDeclarationInScope(name);
+    }
+
+    default Optional<ResolvedFieldDeclaration> fieldDeclarationInScope(String name) {
+        if (getParent() == null) {
+            return Optional.empty();
+        }
+        Optional<ResolvedFieldDeclaration> localRes = getParent().fieldsExposedToChild(((AbstractJavaParserContext)this)
+                .getWrappedNode()).stream().filter(vd -> vd.getName().equals(name)).findFirst();
+        if (localRes.isPresent()) {
+            return localRes;
+        }
+
+        return getParent().fieldDeclarationInScope(name);
+    }
+
     /* Constructor resolution */
 
     /**
      * We find the method declaration which is the best match for the given name and list of typeParametersValues.
      */
-    default SymbolReference<ResolvedConstructorDeclaration> solveConstructor(List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
+    default SymbolReference<ResolvedConstructorDeclaration> solveConstructor(List<ResolvedType> argumentsTypes) {
         throw new IllegalArgumentException("Constructor resolution is available only on Class Context");
     }
 
@@ -79,20 +173,33 @@
     /**
      * We find the method declaration which is the best match for the given name and list of typeParametersValues.
      */
-    SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver);
+    default SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
+                                                                   boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, staticOnly);
+    }
 
     /**
      * Similar to solveMethod but we return a MethodUsage. A MethodUsage corresponds to a MethodDeclaration plus the
      * resolved type variables.
      */
-    default Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
-        SymbolReference<ResolvedMethodDeclaration> methodSolved = solveMethod(name, argumentsTypes, false, typeSolver);
+    default Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes) {
+        SymbolReference<ResolvedMethodDeclaration> methodSolved = solveMethod(name, argumentsTypes, false);
         if (methodSolved.isSolved()) {
             ResolvedMethodDeclaration methodDeclaration = methodSolved.getCorrespondingDeclaration();
-            MethodUsage methodUsage = ContextHelper.resolveTypeVariables(this, methodDeclaration, argumentsTypes);//methodDeclaration.resolveTypeVariables(this, argumentsTypes);
+
+            MethodUsage methodUsage;
+            if (methodDeclaration instanceof TypeVariableResolutionCapability) {
+                methodUsage = ((TypeVariableResolutionCapability) methodDeclaration)
+                                      .resolveTypeVariables(this, argumentsTypes);
+            } else {
+                throw new UnsupportedOperationException("Resolved method declarations should have the " +
+                                                        TypeVariableResolutionCapability.class.getName() + ".");
+            }
+
             return Optional.of(methodUsage);
         } else {
             return Optional.empty();
         }
     }
+
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/ContextHelper.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/ContextHelper.java
deleted file mode 100644
index f314052..0000000
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/ContextHelper.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver.core.resolution;
-
-import com.github.javaparser.resolution.MethodUsage;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration;
-import com.github.javaparser.symbolsolver.javassistmodel.JavassistMethodDeclaration;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionMethodDeclaration;
-
-import java.util.List;
-
-/**
- * @author Federico Tomassetti
- */
-class ContextHelper {
-
-    private ContextHelper() {
-        // prevent instantiation
-    }
-
-    static MethodUsage resolveTypeVariables(Context context, ResolvedMethodDeclaration methodDeclaration, List<ResolvedType> parameterTypes) {
-        if (methodDeclaration instanceof JavaParserMethodDeclaration) {
-            return ((JavaParserMethodDeclaration) methodDeclaration).resolveTypeVariables(context, parameterTypes);
-        } else if (methodDeclaration instanceof JavassistMethodDeclaration) {
-            return ((JavassistMethodDeclaration) methodDeclaration).resolveTypeVariables(context, parameterTypes);
-        } else if (methodDeclaration instanceof JavaParserEnumDeclaration.ValuesMethod) {
-            return ((JavaParserEnumDeclaration.ValuesMethod) methodDeclaration).resolveTypeVariables(context, parameterTypes);
-        } else if (methodDeclaration instanceof ReflectionMethodDeclaration) {
-            return ((ReflectionMethodDeclaration) methodDeclaration).resolveTypeVariables(context, parameterTypes);
-        } else {
-            throw new UnsupportedOperationException();
-        }
-    }
-}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/MethodUsageResolutionCapability.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/MethodUsageResolutionCapability.java
new file mode 100644
index 0000000..fc51a9a
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/MethodUsageResolutionCapability.java
@@ -0,0 +1,12 @@
+package com.github.javaparser.symbolsolver.core.resolution;
+
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.types.ResolvedType;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface MethodUsageResolutionCapability {
+	Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentTypes, Context invocationContext,
+	                                         List<ResolvedType> typeParameters);
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/TypeVariableResolutionCapability.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/TypeVariableResolutionCapability.java
new file mode 100644
index 0000000..5e9afa2
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/core/resolution/TypeVariableResolutionCapability.java
@@ -0,0 +1,10 @@
+package com.github.javaparser.symbolsolver.core.resolution;
+
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.types.ResolvedType;
+
+import java.util.List;
+
+public interface TypeVariableResolutionCapability {
+	MethodUsage resolveTypeVariables(Context context, List<ResolvedType> parameterTypes);
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic.java
index 5d00635..cfa9144 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic.java
@@ -44,10 +44,10 @@
     }
 
     public MethodUsage resolveTypeVariables(Context context, List<ResolvedType> parameterTypes) {
-        ResolvedType returnType = replaceTypeParams(methodDeclaration.getReturnType(), typeSolver, context);
+        ResolvedType returnType = replaceTypeParams(methodDeclaration.getReturnType(), context);
         List<ResolvedType> params = new ArrayList<>();
         for (int i = 0; i < methodDeclaration.getNumberOfParams(); i++) {
-            ResolvedType replaced = replaceTypeParams(methodDeclaration.getParam(i).getType(), typeSolver, context);
+            ResolvedType replaced = replaceTypeParams(methodDeclaration.getParam(i).getType(), context);
             params.add(replaced);
         }
 
@@ -66,11 +66,11 @@
         return new MethodUsage(methodDeclaration, params, returnType);
     }
 
-    private ResolvedType replaceTypeParams(ResolvedType type, TypeSolver typeSolver, Context context) {
+    private ResolvedType replaceTypeParams(ResolvedType type, Context context) {
         if (type.isTypeVariable()) {
             ResolvedTypeParameterDeclaration typeParameter = type.asTypeParameter();
             if (typeParameter.declaredOnType()) {
-                Optional<ResolvedType> typeParam = typeParamByName(typeParameter.getName(), typeSolver, context);
+                Optional<ResolvedType> typeParam = typeParamByName(typeParameter.getName(), context);
                 if (typeParam.isPresent()) {
                     type = typeParam.get();
                 }
@@ -78,13 +78,13 @@
         }
 
         if (type.isReferenceType()) {
-            type.asReferenceType().transformTypeParameters(tp -> replaceTypeParams(tp, typeSolver, context));
+            type.asReferenceType().transformTypeParameters(tp -> replaceTypeParams(tp, context));
         }
 
         return type;
     }
 
-    protected Optional<ResolvedType> typeParamByName(String name, TypeSolver typeSolver, Context context) {
+    protected Optional<ResolvedType> typeParamByName(String name, Context context) {
         return methodDeclaration.getTypeParameters().stream().filter(tp -> tp.getName().equals(name)).map(tp -> toType(tp)).findFirst();
     }
 
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparser/Navigator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparser/Navigator.java
index dc3ea62..31757aa 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparser/Navigator.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparser/Navigator.java
@@ -39,18 +39,16 @@
         // prevent instantiation
     }
 
-    /**
-     * @deprecated use Node.getParentNode
-     */
-    @Deprecated
-    public static Node getParentNode(Node node) {
-        return node.getParentNode().orElse(null);
-    }
-
     public static Node requireParentNode(Node node) {
         return node.getParentNode().orElseThrow(() -> new IllegalStateException("Parent not found, the node does not appear to be inserted in a correct AST"));
     }
 
+    /**
+     * Looks among the type declared in the Compilation Unit for one having the specified name.
+     * The name can be qualified with respect to the compilation unit. For example, if the compilation
+     * unit is in package a.b; and it contains two top level classes named C and D, with class E being defined inside D
+     * then the qualifiedName that can be resolved are "C", "D", and "D.E".
+     */
     public static Optional<TypeDeclaration<?>> findType(CompilationUnit cu, String qualifiedName) {
         if (cu.getTypes().isEmpty()) {
             return Optional.empty();
@@ -66,6 +64,11 @@
         return type;
     }
 
+    /**
+     * Looks among the type declared in the TypeDeclaration for one having the specified name.
+     * The name can be qualified with respect to the TypeDeclaration. For example, if the class declarationd defines class D
+     * and class D contains an internal class named E then the qualifiedName that can be resolved are "D", and "D.E".
+     */
     public static Optional<TypeDeclaration<?>> findType(TypeDeclaration<?> td, String qualifiedName) {
         final String typeName = getOuterTypeName(qualifiedName);
 
@@ -91,6 +94,14 @@
         return cd;
     }
 
+    public static ClassOrInterfaceDeclaration demandInterface(CompilationUnit cu, String qualifiedName) {
+        ClassOrInterfaceDeclaration cd = demandClassOrInterface(cu, qualifiedName);
+        if (!cd.isInterface()) {
+            throw new IllegalStateException("Type is not an interface");
+        }
+        return cd;
+    }
+
     public static EnumDeclaration demandEnum(CompilationUnit cu, String qualifiedName) {
         Optional<TypeDeclaration<?>> res = findType(cu, qualifiedName);
         if (!res.isPresent()) {
@@ -121,6 +132,33 @@
         return found;
     }
 
+    /**
+     * Returns the {@code (i+1)}'th constructor of the given type declaration, in textual order. The constructor that
+     * appears first has the index 0, the second one the index 1, and so on.
+     *
+     * @param td    The type declaration to search in. Note that only classes and enums have constructors.
+     * @param index The index of the desired constructor.
+     * @return The desired ConstructorDeclaration if it was found, and {@code null} otherwise.
+     */
+    public static ConstructorDeclaration demandConstructor(TypeDeclaration<?> td, int index) {
+        ConstructorDeclaration found = null;
+        int i = 0;
+        for (BodyDeclaration<?> bd : td.getMembers()) {
+            if (bd instanceof ConstructorDeclaration) {
+                ConstructorDeclaration cd = (ConstructorDeclaration) bd;
+                if (i == index) {
+                    found = cd;
+                    break;
+                }
+                i++;
+            }
+        }
+        if (found == null) {
+            throw new IllegalStateException("No constructor with index " + index);
+        }
+        return found;
+    }
+
     public static VariableDeclarator demandField(ClassOrInterfaceDeclaration cd, String name) {
         for (BodyDeclaration<?> bd : cd.getMembers()) {
             if (bd instanceof FieldDeclaration) {
@@ -167,27 +205,11 @@
         return node.findFirst(clazz).orElseThrow(IllegalArgumentException::new);
     }
 
-    /**
-     * @deprecated use Node.findAll instead
-     */
-    @Deprecated
-    public static <N extends Node> List<N> findAllNodesOfGivenClass(Node node, Class<N> clazz) {
-        return node.findAll(clazz);
-    }
-
     // TODO should be demand or require...
     public static ReturnStmt findReturnStmt(MethodDeclaration method) {
         return findNodeOfGivenClass(method, ReturnStmt.class);
     }
 
-    /**
-     * @deprecated use Node.findParent instead
-     */
-    @Deprecated
-    public static <N extends Node> Optional<N> findAncestor(Node node, Class<N> clazz) {
-        return node.findParent(clazz);
-    }
-
     ///
     /// Private methods
     ///
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 499ef3b..71f3e3e 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
@@ -329,7 +329,7 @@
     }
 
     @Override
-    public ResolvedType visit(SwitchEntryStmt node, Boolean aBoolean) {
+    public ResolvedType visit(SwitchEntry node, Boolean aBoolean) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
 
@@ -364,7 +364,7 @@
     }
 
     @Override
-    public ResolvedType visit(ForeachStmt node, Boolean aBoolean) {
+    public ResolvedType visit(ForEachStmt node, Boolean aBoolean) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
 
@@ -434,27 +434,27 @@
     }
 
     @Override
-    public ResolvedType visit(ModuleRequiresStmt node, Boolean arg) {
+    public ResolvedType visit(ModuleRequiresDirective node, Boolean arg) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
 
     @Override
-    public ResolvedType visit(ModuleExportsStmt node, Boolean arg) {
+    public ResolvedType visit(ModuleExportsDirective node, Boolean arg) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
 
     @Override
-    public ResolvedType visit(ModuleProvidesStmt node, Boolean arg) {
+    public ResolvedType visit(ModuleProvidesDirective node, Boolean arg) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
 
     @Override
-    public ResolvedType visit(ModuleUsesStmt node, Boolean arg) {
+    public ResolvedType visit(ModuleUsesDirective node, Boolean arg) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
 
     @Override
-    public ResolvedType visit(ModuleOpensStmt node, Boolean arg) {
+    public ResolvedType visit(ModuleOpensDirective node, Boolean arg) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
 
@@ -472,4 +472,14 @@
     public ResolvedType visit(VarType node, Boolean arg) {
         throw new UnsupportedOperationException(node.getClass().getCanonicalName());
     }
+
+    @Override
+    public ResolvedType visit(Modifier node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public ResolvedType visit(SwitchExpr node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java
index f73dd98..5780a8b 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java
@@ -17,10 +17,13 @@
 package com.github.javaparser.symbolsolver.javaparsermodel;
 
 import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.DataKey;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.*;
+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.body.VariableDeclarator;
 import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 import com.github.javaparser.ast.type.*;
@@ -30,18 +33,18 @@
 import com.github.javaparser.resolution.types.*;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
 import com.github.javaparser.symbolsolver.javaparsermodel.contexts.FieldAccessContext;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.*;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.model.typesystem.*;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic;
 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+import com.github.javaparser.utils.Log;
 
 import java.util.*;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
@@ -53,21 +56,15 @@
  */
 public class JavaParserFacade {
 
-    private static Logger logger = Logger.getLogger(JavaParserFacade.class.getCanonicalName());
+    private static final DataKey<ResolvedType> TYPE_WITH_LAMBDAS_RESOLVED = new DataKey<ResolvedType>() {
+    };
+    private static final DataKey<ResolvedType> TYPE_WITHOUT_LAMBDAS_RESOLVED = new DataKey<ResolvedType>() {
+    };
 
-    static {
-        logger.setLevel(Level.INFO);
-        ConsoleHandler consoleHandler = new ConsoleHandler();
-        consoleHandler.setLevel(Level.INFO);
-        logger.addHandler(consoleHandler);
-    }
-
-    private static Map<TypeSolver, JavaParserFacade> instances = new WeakHashMap<>();
-    private TypeSolver typeSolver;
-    private SymbolSolver symbolSolver;
-    private Map<Node, ResolvedType> cacheWithLambdasSolved = new IdentityHashMap<>();
-    private Map<Node, ResolvedType> cacheWithoutLambdasSolved = new IdentityHashMap<>();
-    private TypeExtractor typeExtractor;
+    private static final Map<TypeSolver, JavaParserFacade> instances = new WeakHashMap<>();
+    private final TypeSolver typeSolver;
+    private final TypeExtractor typeExtractor;
+    private final SymbolSolver symbolSolver;
 
     private JavaParserFacade(TypeSolver typeSolver) {
         this.typeSolver = typeSolver.getRoot();
@@ -94,14 +91,14 @@
         instances.clear();
     }
 
-    protected static ResolvedType solveGenericTypes(ResolvedType type, Context context, TypeSolver typeSolver) {
+    protected static ResolvedType solveGenericTypes(ResolvedType type, Context context) {
         if (type.isTypeVariable()) {
-            return context.solveGenericType(type.describe(), typeSolver).orElse(type);
+            return context.solveGenericType(type.describe()).orElse(type);
         }
         if (type.isWildcard()) {
             if (type.asWildcard().isExtends() || type.asWildcard().isSuper()) {
                 ResolvedWildcard wildcardUsage = type.asWildcard();
-                ResolvedType boundResolved = solveGenericTypes(wildcardUsage.getBoundedType(), context, typeSolver);
+                ResolvedType boundResolved = solveGenericTypes(wildcardUsage.getBoundedType(), context);
                 if (wildcardUsage.isExtends()) {
                     return ResolvedWildcard.extendsBound(boundResolved);
                 } else {
@@ -142,7 +139,7 @@
 
         solveArguments(explicitConstructorInvocationStmt, explicitConstructorInvocationStmt.getArguments(), solveLambdas, argumentTypes, placeholders);
 
-        Optional<ClassOrInterfaceDeclaration> optAncestor = explicitConstructorInvocationStmt.getAncestorOfType(ClassOrInterfaceDeclaration.class);
+        Optional<ClassOrInterfaceDeclaration> optAncestor = explicitConstructorInvocationStmt.findAncestor(ClassOrInterfaceDeclaration.class);
         if (!optAncestor.isPresent()) {
             return SymbolReference.unsolved(ResolvedConstructorDeclaration.class);
         }
@@ -154,7 +151,7 @@
                 typeDecl = classDecl.asReferenceType().getTypeDeclaration();
             }
         } else {
-            SymbolReference<ResolvedTypeDeclaration> sr = JavaParserFactory.getContext(classNode, typeSolver).solveType(classNode.getNameAsString(), typeSolver);
+            SymbolReference<ResolvedTypeDeclaration> sr = JavaParserFactory.getContext(classNode, typeSolver).solveType(classNode.getNameAsString());
             if (sr.isSolved()) {
                 typeDecl = sr.getCorrespondingDeclaration();
             }
@@ -171,16 +168,16 @@
 
     public SymbolReference<ResolvedTypeDeclaration> solve(ThisExpr node) {
         // If 'this' is prefixed by a class eg. MyClass.this
-        if (node.getClassExpr().isPresent()) {
+        if (node.getTypeName().isPresent()) {
             // Get the class name
-            String className = node.getClassExpr().get().toString();
+            String className = node.getTypeName().get().asString();
             // Attempt to resolve using a typeSolver
             SymbolReference<ResolvedReferenceTypeDeclaration> clazz = typeSolver.tryToSolveType(className);
             if (clazz.isSolved()) {
                 return SymbolReference.solved(clazz.getCorrespondingDeclaration());
             }
             // Attempt to resolve locally in Compilation unit
-            Optional<CompilationUnit> cu = node.getAncestorOfType(CompilationUnit.class);
+            Optional<CompilationUnit> cu = node.findAncestor(CompilationUnit.class);
             if (cu.isPresent()) {
                 Optional<ClassOrInterfaceDeclaration> classByName = cu.get().getClassByName(className);
                 if (classByName.isPresent()) {
@@ -204,7 +201,7 @@
         if (!classDecl.isReferenceType()) {
             return SymbolReference.unsolved(ResolvedConstructorDeclaration.class);
         }
-        SymbolReference<ResolvedConstructorDeclaration> res = ConstructorResolutionLogic.findMostApplicable(((ResolvedClassDeclaration) classDecl.asReferenceType().getTypeDeclaration()).getConstructors(), argumentTypes, typeSolver);
+        SymbolReference<ResolvedConstructorDeclaration> res = ConstructorResolutionLogic.findMostApplicable(classDecl.asReferenceType().getTypeDeclaration().getConstructors(), argumentTypes, typeSolver);
         for (LambdaArgumentTypePlaceholder placeholder : placeholders) {
             placeholder.setMethod(res);
         }
@@ -242,7 +239,7 @@
 
         solveArguments(methodCallExpr, methodCallExpr.getArguments(), solveLambdas, argumentTypes, placeholders);
 
-        SymbolReference<ResolvedMethodDeclaration> res = JavaParserFactory.getContext(methodCallExpr, typeSolver).solveMethod(methodCallExpr.getName().getId(), argumentTypes, false, typeSolver);
+        SymbolReference<ResolvedMethodDeclaration> res = JavaParserFactory.getContext(methodCallExpr, typeSolver).solveMethod(methodCallExpr.getName().getId(), argumentTypes, false);
         for (LambdaArgumentTypePlaceholder placeholder : placeholders) {
             placeholder.setMethod(res);
         }
@@ -251,85 +248,108 @@
 
     public SymbolReference<ResolvedAnnotationDeclaration> solve(AnnotationExpr annotationExpr) {
         Context context = JavaParserFactory.getContext(annotationExpr, typeSolver);
-        SymbolReference<ResolvedTypeDeclaration> typeDeclarationSymbolReference = context.solveType(annotationExpr.getNameAsString(), typeSolver);
-        ResolvedAnnotationDeclaration annotationDeclaration = (ResolvedAnnotationDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration();
+        SymbolReference<ResolvedTypeDeclaration> typeDeclarationSymbolReference = context.solveType(annotationExpr.getNameAsString());
         if (typeDeclarationSymbolReference.isSolved()) {
+            ResolvedAnnotationDeclaration annotationDeclaration = (ResolvedAnnotationDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration();
             return SymbolReference.solved(annotationDeclaration);
         } else {
             return SymbolReference.unsolved(ResolvedAnnotationDeclaration.class);
         }
     }
 
-    public SymbolReference<ResolvedFieldDeclaration> solve(FieldAccessExpr fieldAccessExpr) {
-        return ((FieldAccessContext) JavaParserFactory.getContext(fieldAccessExpr, typeSolver)).solveField(fieldAccessExpr.getName().getId(), typeSolver);
+    public SymbolReference<ResolvedValueDeclaration> solve(FieldAccessExpr fieldAccessExpr) {
+        return ((FieldAccessContext) JavaParserFactory.getContext(fieldAccessExpr, typeSolver)).solveField(fieldAccessExpr.getName().getId());
     }
 
+    /**
+     * Get the type associated with the node.
+     * <p>
+     * This method was originally intended to get the type of a value: any value has a type.
+     * <p>
+     * For example:
+     * <pre>
+     * int foo(int a) {
+     *     return a; // when getType is invoked on "a" it returns the type "int"
+     * }
+     * </pre>
+     * <p>
+     * Now, users started using also of names of types itself, which do not have a type.
+     * <p>
+     * For example:
+     * <pre>
+     * class A {
+     *     int foo(int a) {
+     *         return A.someStaticField; // when getType is invoked on "A", which represents a class, it returns
+     *             // the type "A" itself while it used to throw UnsolvedSymbolException
+     * }
+     * </pre>
+     * <p>
+     * To accomodate this usage and avoid confusion this method return
+     * the type itself when used on the name of type.
+     */
     public ResolvedType getType(Node node) {
-        return getType(node, true);
+        try {
+            return getType(node, true);
+        } catch (UnsolvedSymbolException e) {
+            if (node instanceof NameExpr) {
+                NameExpr nameExpr = (NameExpr) node;
+                SymbolReference<ResolvedTypeDeclaration> typeDeclaration = JavaParserFactory.getContext(node, typeSolver)
+                        .solveType(nameExpr.getNameAsString());
+                if (typeDeclaration.isSolved() && typeDeclaration.getCorrespondingDeclaration() instanceof ResolvedReferenceTypeDeclaration) {
+                    ResolvedReferenceTypeDeclaration resolvedReferenceTypeDeclaration = (ResolvedReferenceTypeDeclaration) typeDeclaration.getCorrespondingDeclaration();
+                    return ReferenceTypeImpl.undeterminedParameters(resolvedReferenceTypeDeclaration, typeSolver);
+                }
+            }
+            throw e;
+        }
     }
 
     public ResolvedType getType(Node node, boolean solveLambdas) {
         if (solveLambdas) {
-            if (!cacheWithLambdasSolved.containsKey(node)) {
+            if (!node.containsData(TYPE_WITH_LAMBDAS_RESOLVED)) {
                 ResolvedType res = getTypeConcrete(node, solveLambdas);
 
-                cacheWithLambdasSolved.put(node, res);
+                node.setData(TYPE_WITH_LAMBDAS_RESOLVED, res);
 
                 boolean secondPassNecessary = false;
                 if (node instanceof MethodCallExpr) {
                     MethodCallExpr methodCallExpr = (MethodCallExpr) node;
                     for (Node arg : methodCallExpr.getArguments()) {
-                        if (!cacheWithLambdasSolved.containsKey(arg)) {
+                        if (!arg.containsData(TYPE_WITH_LAMBDAS_RESOLVED)) {
                             getType(arg, true);
                             secondPassNecessary = true;
                         }
                     }
                 }
                 if (secondPassNecessary) {
-                    cacheWithLambdasSolved.remove(node);
-                    cacheWithLambdasSolved.put(node, getType(node, true));
+                    node.removeData(TYPE_WITH_LAMBDAS_RESOLVED);
+                    ResolvedType type = getType(node, true);
+                    node.setData(TYPE_WITH_LAMBDAS_RESOLVED, type);
+
                 }
-                logger.finer("getType on " + node + " -> " + res);
+                Log.trace("getType on %s  -> %s" ,()-> node, ()-> res);
             }
-            return cacheWithLambdasSolved.get(node);
+            return node.getData(TYPE_WITH_LAMBDAS_RESOLVED);
         } else {
-            Optional<ResolvedType> res = find(cacheWithLambdasSolved, node);
+            Optional<ResolvedType> res = find(TYPE_WITH_LAMBDAS_RESOLVED, node);
             if (res.isPresent()) {
                 return res.get();
             }
-            res = find(cacheWithoutLambdasSolved, node);
+            res = find(TYPE_WITHOUT_LAMBDAS_RESOLVED, node);
             if (!res.isPresent()) {
                 ResolvedType resType = getTypeConcrete(node, solveLambdas);
-                cacheWithoutLambdasSolved.put(node, resType);
-                logger.finer("getType on " + node + " (no solveLambdas) -> " + res);
+                node.setData(TYPE_WITHOUT_LAMBDAS_RESOLVED, resType);
+                Optional<ResolvedType> finalRes = res;
+                Log.trace("getType on %s (no solveLambdas) -> %s", ()-> node, ()-> finalRes);
                 return resType;
             }
             return res.get();
         }
     }
 
-    private Optional<ResolvedType> find(Map<Node, ResolvedType> map, Node node) {
-        if (map.containsKey(node)) {
-            return Optional.of(map.get(node));
-        }
-        if (node instanceof LambdaExpr) {
-            return find(map, (LambdaExpr) node);
-        } else {
-            return Optional.empty();
-        }
-    }
-
-    /**
-     * For some reasons LambdaExprs are duplicate and the equals method is not implemented correctly.
-     */
-    private Optional<ResolvedType> find(Map<Node, ResolvedType> map, LambdaExpr lambdaExpr) {
-        for (Node key : map.keySet()) {
-            if (key instanceof LambdaExpr) {
-                LambdaExpr keyLambdaExpr = (LambdaExpr) key;
-                if (keyLambdaExpr.toString().equals(lambdaExpr.toString()) && requireParentNode(keyLambdaExpr) == requireParentNode(lambdaExpr)) {
-                    return Optional.of(map.get(keyLambdaExpr));
-                }
-            }
+    private Optional<ResolvedType> find(DataKey<ResolvedType> dataKey, Node node) {
+        if (node.containsData(dataKey)) {
+            return Optional.of(node.getData(dataKey));
         }
         return Optional.empty();
     }
@@ -343,7 +363,7 @@
             throw new UnsupportedOperationException(typeExpr.getType().getClass().getCanonicalName());
         }
         ClassOrInterfaceType classOrInterfaceType = (ClassOrInterfaceType) typeExpr.getType();
-        SymbolReference<ResolvedTypeDeclaration> typeDeclarationSymbolReference = JavaParserFactory.getContext(classOrInterfaceType, typeSolver).solveType(classOrInterfaceType.getName().getId(), typeSolver);
+        SymbolReference<ResolvedTypeDeclaration> typeDeclarationSymbolReference = JavaParserFactory.getContext(classOrInterfaceType, typeSolver).solveType(classOrInterfaceType.getName().getId());
         if (!typeDeclarationSymbolReference.isSolved()) {
             throw new UnsupportedOperationException();
         }
@@ -358,9 +378,60 @@
         }
     }
 
-    protected ResolvedType getBinaryTypeConcrete(Node left, Node right, boolean solveLambdas) {
+    protected ResolvedType getBinaryTypeConcrete(Node left, Node right, boolean solveLambdas, BinaryExpr.Operator operator) {
         ResolvedType leftType = getTypeConcrete(left, solveLambdas);
         ResolvedType rightType = getTypeConcrete(right, solveLambdas);
+
+        // JLS 15.18.1. String Concatenation Operator +
+        // If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other
+        // operand to produce a string at run time.
+        //
+        // The result of string concatenation is a reference to a String object that is the concatenation of the two
+        // operand strings. The characters of the left-hand operand precede the characters of the right-hand operand in
+        // the newly created string.
+
+        if (operator == BinaryExpr.Operator.PLUS) {
+            boolean isLeftString = leftType.isReferenceType() && leftType.asReferenceType()
+                    .getQualifiedName().equals(String.class.getCanonicalName());
+            boolean isRightString = rightType.isReferenceType() && rightType.asReferenceType()
+                    .getQualifiedName().equals(String.class.getCanonicalName());
+            if (isLeftString || isRightString) {
+                return isLeftString ? leftType : rightType;
+            }
+        }
+
+        // JLS 5.6.2. Binary Numeric Promotion
+        //
+        // Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the
+        // following rules:
+        //
+        // * If either operand is of type double, the other is converted to double.
+        // * Otherwise, if either operand is of type float, the other is converted to float.
+        // * Otherwise, if either operand is of type long, the other is converted to long.
+        // * Otherwise, both operands are converted to type int.
+
+        boolean isLeftNumeric = leftType.isPrimitive() && leftType.asPrimitive().isNumeric();
+        boolean isRightNumeric = rightType.isPrimitive() && rightType.asPrimitive().isNumeric();
+
+        if (isLeftNumeric && isRightNumeric) {
+            if (leftType.asPrimitive().equals(ResolvedPrimitiveType.DOUBLE)
+                    || rightType.asPrimitive().equals(ResolvedPrimitiveType.DOUBLE)) {
+                return ResolvedPrimitiveType.DOUBLE;
+            }
+
+            if (leftType.asPrimitive().equals(ResolvedPrimitiveType.FLOAT)
+                    || rightType.asPrimitive().equals(ResolvedPrimitiveType.FLOAT)) {
+                return ResolvedPrimitiveType.FLOAT;
+            }
+
+            if (leftType.asPrimitive().equals(ResolvedPrimitiveType.LONG)
+                    || rightType.asPrimitive().equals(ResolvedPrimitiveType.LONG)) {
+                return ResolvedPrimitiveType.LONG;
+            }
+
+            return ResolvedPrimitiveType.INT;
+        }
+
         if (rightType.isAssignableBy(leftType)) {
             return rightType;
         }
@@ -433,7 +504,7 @@
         if (type instanceof ClassOrInterfaceType) {
             ClassOrInterfaceType classOrInterfaceType = (ClassOrInterfaceType) type;
             String name = qName(classOrInterfaceType);
-            SymbolReference<ResolvedTypeDeclaration> ref = context.solveType(name, typeSolver);
+            SymbolReference<ResolvedTypeDeclaration> ref = context.solveType(name);
             if (!ref.isSolved()) {
                 throw new UnsolvedSymbolException(name);
             }
@@ -510,7 +581,7 @@
             }
         }
         Context context = JavaParserFactory.getContext(call, typeSolver);
-        Optional<MethodUsage> methodUsage = context.solveMethodAsUsage(call.getName().getId(), params, typeSolver);
+        Optional<MethodUsage> methodUsage = context.solveMethodAsUsage(call.getName().getId(), params);
         if (!methodUsage.isPresent()) {
             throw new RuntimeException("Method '" + call.getName() + "' cannot be resolved in context "
                     + call + " (line: " + call.getRange().map(r -> "" + r.begin.line).orElse("??") + ") " + context + ". Parameter types: " + params);
@@ -557,6 +628,6 @@
         if (clazz.isPrimitive()) {
             return ResolvedPrimitiveType.byName(clazz.getName());
         }
-        return new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
+        return new ReferenceTypeImpl(new ReflectionClassDeclaration(clazz, typeSolver), typeSolver);
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java
index 8bd3496..7fb38be 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java
@@ -25,11 +25,7 @@
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
 import com.github.javaparser.symbolsolver.javaparsermodel.contexts.*;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnnotationDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.*;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarators.FieldSymbolDeclarator;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarators.NoSymbolDeclarator;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarators.ParameterSymbolDeclarator;
@@ -37,7 +33,6 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
 
 /**
@@ -48,10 +43,12 @@
     public static Context getContext(Node node, TypeSolver typeSolver) {
         if (node == null) {
             throw new NullPointerException("Node should not be null");
+        } else if (node instanceof BlockStmt) {
+            return new BlockStmtContext((BlockStmt) node, typeSolver);
         } else if (node instanceof CompilationUnit) {
             return new CompilationUnitContext((CompilationUnit) node, typeSolver);
-        } else if (node instanceof ForeachStmt) {
-            return new ForechStatementContext((ForeachStmt) node, typeSolver);
+        } else if (node instanceof ForEachStmt) {
+            return new ForEachStatementContext((ForEachStmt) node, typeSolver);
         } else if (node instanceof ForStmt) {
             return new ForStatementContext((ForStmt) node, typeSolver);
         } else if (node instanceof LambdaExpr) {
@@ -68,26 +65,37 @@
             return new EnumDeclarationContext((EnumDeclaration) node, typeSolver);
         } else if (node instanceof FieldAccessExpr) {
             return new FieldAccessContext((FieldAccessExpr) node, typeSolver);
-        } else if (node instanceof SwitchEntryStmt) {
-            return new SwitchEntryContext((SwitchEntryStmt) node, typeSolver);
+        } else if (node instanceof SwitchEntry) {
+            return new SwitchEntryContext((SwitchEntry) node, typeSolver);
         } else if (node instanceof TryStmt) {
             return new TryWithResourceContext((TryStmt) node, typeSolver);
         } else if (node instanceof Statement) {
             return new StatementContext<>((Statement) node, typeSolver);
         } else if (node instanceof CatchClause) {
             return new CatchClauseContext((CatchClause) node, typeSolver);
+        } else if (node instanceof VariableDeclarator) {
+            return new VariableDeclaratorContext((VariableDeclarator) node, typeSolver);
+        } else if (node instanceof VariableDeclarationExpr) {
+            return new VariableDeclarationExprContext((VariableDeclarationExpr) node, typeSolver);
         } else if (node instanceof ObjectCreationExpr &&
             ((ObjectCreationExpr) node).getAnonymousClassBody().isPresent()) {
             return new AnonymousClassDeclarationContext((ObjectCreationExpr) node, typeSolver);
+        } else if (node instanceof ObjectCreationExpr) {
+            return new ObjectCreationContext((ObjectCreationExpr)node, typeSolver);
         } else {
             if (node instanceof NameExpr) {
                 // to resolve a name when in a fieldAccess context, we can get to the grand parent to prevent a infinite loop if the name is the same as the field (ie x.x)
                 if (node.getParentNode().isPresent() && node.getParentNode().get() instanceof FieldAccessExpr && node.getParentNode().get().getParentNode().isPresent()) {
                     return getContext(node.getParentNode().get().getParentNode().get(), typeSolver);
                 }
+                if (node.getParentNode().isPresent() && node.getParentNode().get() instanceof ObjectCreationExpr && node.getParentNode().get().getParentNode().isPresent()) {
+                    return getContext(node.getParentNode().get().getParentNode().get(), typeSolver);
+                }
             }
             final Node parentNode = requireParentNode(node);
-            if (parentNode instanceof ObjectCreationExpr && node == ((ObjectCreationExpr) parentNode).getType()) {
+            if (parentNode instanceof ObjectCreationExpr
+                    && (node == ((ObjectCreationExpr) parentNode).getType()
+                        || ((ObjectCreationExpr) parentNode).getArguments().contains(node))) {
                 return getContext(requireParentNode(parentNode), typeSolver);
             }
             if (parentNode == null) {
@@ -111,8 +119,8 @@
             }
         } else if (node instanceof IfStmt) {
             return new NoSymbolDeclarator<>((IfStmt) node, typeSolver);
-        } else if (node instanceof ForeachStmt) {
-            ForeachStmt foreachStmt = (ForeachStmt) node;
+        } else if (node instanceof ForEachStmt) {
+            ForEachStmt foreachStmt = (ForEachStmt) node;
             return new VariableSymbolDeclarator(foreachStmt.getVariable(), typeSolver);
         } else {
             return new NoSymbolDeclarator<>(node, typeSolver);
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 44c8d27..908a3d0 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
@@ -32,28 +32,17 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.utils.Log;
 import com.google.common.collect.ImmutableList;
 
 import java.util.List;
 import java.util.Optional;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
 import static com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveGenericTypes;
 
 public class TypeExtractor extends DefaultVisitorAdapter {
 
-    private static Logger logger = Logger.getLogger(TypeExtractor.class.getCanonicalName());
-
-    static {
-        logger.setLevel(Level.INFO);
-        ConsoleHandler consoleHandler = new ConsoleHandler();
-        consoleHandler.setLevel(Level.INFO);
-        logger.addHandler(consoleHandler);
-    }
-
     private TypeSolver typeSolver;
     private JavaParserFacade facade;
 
@@ -116,7 +105,7 @@
             case MINUS:
             case DIVIDE:
             case MULTIPLY:
-                return facade.getBinaryTypeConcrete(node.getLeft(), node.getRight(), solveLambdas);
+                return facade.getBinaryTypeConcrete(node.getLeft(), node.getRight(), solveLambdas, node.getOperator());
             case LESS_EQUALS:
             case LESS:
             case GREATER:
@@ -169,7 +158,9 @@
     private ResolvedType solveDotExpressionType(ResolvedReferenceTypeDeclaration parentType, FieldAccessExpr node) {
         // Fields and internal type declarations cannot have the same name.
         // Thus, these checks will always be mutually exclusive.
-        if (parentType.hasField(node.getName().getId())) {
+        if (parentType.isEnum() && parentType.asEnum().hasEnumConstant(node.getName().getId())) {
+            return parentType.asEnum().getEnumConstant(node.getName().getId()).getType();
+        } else if (parentType.hasField(node.getName().getId())) {
             return parentType.getField(node.getName().getId()).getType();
         } else if (parentType.hasInternalType(node.getName().getId())) {
             return new ReferenceTypeImpl(parentType.getInternalType(node.getName().getId()), typeSolver);
@@ -184,7 +175,7 @@
         if (node.getScope() instanceof NameExpr ||
                 node.getScope() instanceof FieldAccessExpr) {
             Expression staticValue = node.getScope();
-            SymbolReference<ResolvedTypeDeclaration> typeAccessedStatically = JavaParserFactory.getContext(node, typeSolver).solveType(staticValue.toString(), typeSolver);
+            SymbolReference<ResolvedTypeDeclaration> typeAccessedStatically = JavaParserFactory.getContext(node, typeSolver).solveType(staticValue.toString());
             if (typeAccessedStatically.isSolved()) {
                 // TODO here maybe we have to substitute type typeParametersValues
                 return solveDotExpressionType(
@@ -271,18 +262,18 @@
 
     @Override
     public ResolvedType visit(MethodCallExpr node, Boolean solveLambdas) {
-        logger.finest("getType on method call " + node);
+        Log.trace("getType on method call %s", ()-> node);
         // first solve the method
         MethodUsage ref = facade.solveMethodAsUsage(node);
-        logger.finest("getType on method call " + node + " resolved to " + ref);
-        logger.finest("getType on method call " + node + " return type is " + ref.returnType());
+        Log.trace("getType on method call %s resolved to %s", ()-> node, ()-> ref);
+        Log.trace("getType on method call %s return type is %s", ()-> node, ref::returnType);
         return ref.returnType();
         // the type is the return type of the method
     }
 
     @Override
     public ResolvedType visit(NameExpr node, Boolean solveLambdas) {
-        logger.finest("getType on name expr " + node);
+        Log.trace("getType on name expr %s", ()-> node);
         Optional<Value> value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getName().getId(), node);
         if (!value.isPresent()) {
             throw new com.github.javaparser.resolution.UnsolvedSymbolException("Solving " + node, node.getName().getId());
@@ -299,16 +290,16 @@
     @Override
     public ResolvedType visit(ThisExpr node, Boolean solveLambdas) {
         // If 'this' is prefixed by a class eg. MyClass.this
-        if (node.getClassExpr().isPresent()) {
+        if (node.getTypeName().isPresent()) {
             // Get the class name
-            String className = node.getClassExpr().get().toString();
+            String className = node.getTypeName().get().asString();
             // Attempt to resolve using a typeSolver
             SymbolReference<ResolvedReferenceTypeDeclaration> clazz = typeSolver.tryToSolveType(className);
             if (clazz.isSolved()) {
                 return new ReferenceTypeImpl(clazz.getCorrespondingDeclaration(), typeSolver);
             }
             // Attempt to resolve locally in Compilation unit
-            Optional<CompilationUnit> cu = node.getAncestorOfType(CompilationUnit.class);
+            Optional<CompilationUnit> cu = node.findAncestor(CompilationUnit.class);
             if (cu.isPresent()) {
                 Optional<ClassOrInterfaceDeclaration> classByName = cu.get().getClassByName(className);
                 if (classByName.isPresent()) {
@@ -366,7 +357,7 @@
             if (!refMethod.isSolved()) {
                 throw new com.github.javaparser.resolution.UnsolvedSymbolException(requireParentNode(node).toString(), callExpr.getName().getId());
             }
-            logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName());
+            Log.trace("getType on lambda expr %s", ()-> refMethod.getCorrespondingDeclaration().getName());
             if (solveLambdas) {
 
                 // The type parameter referred here should be the java.util.stream.Stream.T
@@ -380,7 +371,7 @@
                     if (scope instanceof NameExpr) {
                         NameExpr nameExpr = (NameExpr) scope;
                         try {
-                            SymbolReference<ResolvedTypeDeclaration> type = JavaParserFactory.getContext(nameExpr, typeSolver).solveType(nameExpr.getName().getId(), typeSolver);
+                            SymbolReference<ResolvedTypeDeclaration> type = JavaParserFactory.getContext(nameExpr, typeSolver).solveType(nameExpr.getName().getId());
                             if (type.isSolved()) {
                                 staticCall = true;
                             }
@@ -399,7 +390,7 @@
 
                 // We need to replace the type variables
                 Context ctx = JavaParserFactory.getContext(node, typeSolver);
-                result = solveGenericTypes(result, ctx, typeSolver);
+                result = solveGenericTypes(result, ctx);
 
                 //We should find out which is the functional method (e.g., apply) and replace the params of the
                 //solveLambdas with it, to derive so the values. We should also consider the value returned by the
@@ -477,14 +468,13 @@
             if (!refMethod.isSolved()) {
                 throw new com.github.javaparser.resolution.UnsolvedSymbolException(requireParentNode(node).toString(), callExpr.getName().getId());
             }
-            logger.finest("getType on method reference expr " + refMethod.getCorrespondingDeclaration().getName());
-            //logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos));
+            Log.trace("getType on method reference expr %s", ()-> refMethod.getCorrespondingDeclaration().getName());
             if (solveLambdas) {
                 MethodUsage usage = facade.solveMethodAsUsage(callExpr);
                 ResolvedType result = usage.getParamType(pos);
                 // We need to replace the type variables
                 Context ctx = JavaParserFactory.getContext(node, typeSolver);
-                result = solveGenericTypes(result, ctx, typeSolver);
+                result = solveGenericTypes(result, ctx);
 
                 //We should find out which is the functional method (e.g., apply) and replace the params of the
                 //solveLambdas with it, to derive so the values. We should also consider the value returned by the
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java
deleted file mode 100644
index f7ab7d1..0000000
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver.javaparsermodel;
-
-import com.github.javaparser.symbolsolver.core.resolution.Context;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-
-/**
- * @author Federico Tomassetti
- *
- * @deprecated Use {@link com.github.javaparser.resolution.UnsolvedSymbolException} instead
- */
-// Use the one in model instead
-@Deprecated
-public class UnsolvedSymbolException extends RuntimeException {
-
-    private String context;
-    private String name;
-    private TypeSolver typeSolver;
-
-    @Deprecated
-    public UnsolvedSymbolException(String name, TypeSolver typeSolver) {
-        super("Unsolved symbol : " + name + " using typesolver " + typeSolver);
-        this.typeSolver = typeSolver;
-        this.name = name;
-    }
-
-    @Deprecated
-    public UnsolvedSymbolException(Context context, String name) {
-        super("Unsolved symbol in " + context + " : " + name);
-        this.context = context.toString();
-        this.name = name;
-    }
-
-    @Deprecated
-    public UnsolvedSymbolException(String context, String name) {
-        super("Unsolved symbol in " + context + " : " + name);
-        this.context = context;
-        this.name = name;
-    }
-
-    @Deprecated
-    public UnsolvedSymbolException(String name) {
-        super("Unsolved symbol : " + name);
-        this.context = "unknown";
-        this.name = name;
-    }
-
-    @Override
-    public String toString() {
-        return "UnsolvedSymbolException{" +
-                "context='" + context + '\'' +
-                ", name='" + name + '\'' +
-                ", typeSolver=" + typeSolver +
-                '}';
-    }
-}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java
index cc008a5..728a60b 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java
@@ -21,10 +21,12 @@
 import com.github.javaparser.ast.expr.FieldAccessExpr;
 import com.github.javaparser.ast.expr.MethodCallExpr;
 import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
@@ -35,11 +37,13 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
-import static java.util.Collections.*;
+import static java.util.Collections.singletonList;
 
 /**
  * @author Federico Tomassetti
@@ -85,9 +89,7 @@
 
         AbstractJavaParserContext<?> that = (AbstractJavaParserContext<?>) o;
 
-        if (wrappedNode != null ? !wrappedNode.equals(that.wrappedNode) : that.wrappedNode != null) return false;
-
-        return true;
+        return wrappedNode != null ? wrappedNode.equals(that.wrappedNode) : that.wrappedNode == null;
     }
 
     @Override
@@ -96,12 +98,12 @@
     }
 
     @Override
-    public Optional<ResolvedType> solveGenericType(String name, TypeSolver typeSolver) {
+    public Optional<ResolvedType> solveGenericType(String name) {
         Context parent = getParent();
         if (parent == null) {
             return Optional.empty();
         } else {
-            return parent.solveGenericType(name, typeSolver);
+            return parent.solveGenericType(name);
         }
     }
 
@@ -140,21 +142,21 @@
     /// Protected methods
     ///
 
-    protected Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) {
+    protected Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, String name) {
         return symbolDeclarator.getSymbolDeclarations().stream()
                 .filter(d -> d.getName().equals(name))
                 .map(Value::from)
                 .findFirst();
     }
 
-    protected Collection<ResolvedReferenceTypeDeclaration> findTypeDeclarations(Optional<Expression> optScope, TypeSolver typeSolver) {
+    protected Collection<ResolvedReferenceTypeDeclaration> findTypeDeclarations(Optional<Expression> optScope) {
         if (optScope.isPresent()) {
             Expression scope = optScope.get();
 
             // consider static methods
             if (scope instanceof NameExpr) {
-                NameExpr scopeAsName = (NameExpr) scope;
-                SymbolReference<ResolvedTypeDeclaration> symbolReference = this.solveType(scopeAsName.getName().getId(), typeSolver);
+                NameExpr scopeAsName = scope.asNameExpr();
+                SymbolReference<ResolvedTypeDeclaration> symbolReference = this.solveType(scopeAsName.getName().getId());
                 if (symbolReference.isSolved() && symbolReference.getCorrespondingDeclaration().isType()) {
                     return singletonList(symbolReference.getCorrespondingDeclaration().asReferenceType());
                 }
@@ -164,7 +166,14 @@
             try {
                 typeOfScope = JavaParserFacade.get(typeSolver).getType(scope);
             } catch (Exception e) {
-                throw new RuntimeException("Issue calculating the type of the scope of " + this, e);
+                // If the scope corresponds to a type we should treat it differently
+                if (scope instanceof FieldAccessExpr) {
+                    FieldAccessExpr scopeName = (FieldAccessExpr) scope;
+                    if (this.solveType(scopeName.toString()).isSolved()) {
+                        return Collections.emptyList();
+                    }
+                }
+                throw new UnsolvedSymbolException(scope.toString(), wrappedNode.toString(), e);
             }
             if (typeOfScope.isWildcard()) {
                 if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) {
@@ -183,6 +192,12 @@
                 return result;
             } else if (typeOfScope.isConstraint()) {
                 return singletonList(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration());
+            } else if (typeOfScope.isUnionType()) {
+                return typeOfScope.asUnionType().getCommonAncestor()
+                        .map(ResolvedReferenceType::getTypeDeclaration)
+                        .map(Collections::singletonList)
+                        .orElseThrow(() -> new UnsolvedSymbolException("No common ancestor available for UnionType"
+                                + typeOfScope.describe()));
             }
             return singletonList(typeOfScope.asReferenceType().getTypeDeclaration());
         }
@@ -190,4 +205,7 @@
         return singletonList(typeOfScope.asReferenceType().getTypeDeclaration());
     }
 
+    public N getWrappedNode() {
+        return wrappedNode;
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java
index d611d71..be275bc 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java
@@ -30,7 +30,7 @@
         super(wrappedNode, typeSolver);
     }
 
-    public final SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public final SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         for (Parameter parameter : wrappedNode.getParameters()) {
             SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
             SymbolReference<? extends ResolvedValueDeclaration> symbolReference = AbstractJavaParserContext.solveWith(sb, name);
@@ -40,24 +40,24 @@
         }
 
         // if nothing is found we should ask the parent context
-        return getParent().solveSymbol(name, typeSolver);
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public final Optional<ResolvedType> solveGenericType(String name, TypeSolver typeSolver) {
+    public final Optional<ResolvedType> solveGenericType(String name) {
         for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) {
             if (tp.getName().getId().equals(name)) {
                 return Optional.of(new ResolvedTypeVariable(new JavaParserTypeParameter(tp, typeSolver)));
             }
         }
-        return super.solveGenericType(name, typeSolver);
+        return super.solveGenericType(name);
     }
 
     @Override
-    public final Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public final Optional<Value> solveSymbolAsValue(String name) {
         for (Parameter parameter : wrappedNode.getParameters()) {
             SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
-            Optional<Value> symbolReference = solveWithAsValue(sb, name, typeSolver);
+            Optional<Value> symbolReference = solveWithAsValue(sb, name);
             if (symbolReference.isPresent()) {
                 // Perform parameter type substitution as needed
                 return symbolReference;
@@ -65,11 +65,11 @@
         }
 
         // if nothing is found we should ask the parent context
-        return getParent().solveSymbolAsValue(name, typeSolver);
+        return getParent().solveSymbolAsValue(name);
     }
 
     @Override
-    public final SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    public final SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
         if (wrappedNode.getTypeParameters() != null) {
             for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) {
                 if (tp.getName().getId().equals(name)) {
@@ -86,16 +86,16 @@
                 return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(localType));
             } else if (name.startsWith(String.format("%s.", localType.getName()))) {
                 return JavaParserFactory.getContext(localType, typeSolver).solveType(
-                        name.substring(localType.getName().getId().length() + 1), typeSolver);
+                        name.substring(localType.getName().getId().length() + 1));
             }
         }
         
-        return getParent().solveType(name, typeSolver);
+        return getParent().solveType(name);
     }
 
     @Override
     public final SymbolReference<ResolvedMethodDeclaration> solveMethod(
-            String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+            String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java
index 4813359..4f0bccf 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java
@@ -41,8 +41,7 @@
   @Override
   public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name,
                                                                 List<ResolvedType> argumentsTypes,
-                                                                boolean staticOnly,
-                                                                TypeSolver typeSolver) {
+                                                                boolean staticOnly) {
     List<ResolvedMethodDeclaration> candidateMethods =
         myDeclaration
             .getDeclaredMethods()
@@ -56,8 +55,7 @@
             MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(),
                                                     name,
                                                     argumentsTypes,
-                                                    staticOnly,
-                                                    typeSolver);
+                                                    staticOnly);
         // consider methods from superclasses and only default methods from interfaces :
         // not true, we should keep abstract as a valid candidate
         // abstract are removed in MethodResolutionLogic.isApplicable is necessary
@@ -71,7 +69,7 @@
     // see issue #75
     if (candidateMethods.isEmpty()) {
       SymbolReference<ResolvedMethodDeclaration> parentSolution =
-          getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+          getParent().solveMethod(name, argumentsTypes, staticOnly);
       if (parentSolution.isSolved()) {
         candidateMethods.add(parentSolution.getCorrespondingDeclaration());
       }
@@ -84,8 +82,7 @@
                                                                                  typeSolver),
                                                   name,
                                                   argumentsTypes,
-                                                  false,
-                                                  typeSolver);
+                                                  false);
       if (res.isSolved()) {
         candidateMethods.add(res.getCorrespondingDeclaration());
       }
@@ -98,7 +95,7 @@
   }
 
   @Override
-  public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+  public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
     List<com.github.javaparser.ast.body.TypeDeclaration> typeDeclarations =
         myDeclaration
             .findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class);
@@ -124,8 +121,7 @@
             .map(internalType ->
                      JavaParserFactory
                          .getContext(internalType, typeSolver)
-                         .solveType(name.substring(internalType.getName().getId().length() + 1),
-                                    typeSolver));
+                         .solveType(name.substring(internalType.getName().getId().length() + 1)));
 
     if (recursiveMatch.isPresent()) {
       return recursiveMatch.get();
@@ -168,19 +164,18 @@
       }
     }
     
-    return getParent().solveType(name, typeSolver);
+    return getParent().solveType(name);
   }
 
   @Override
-  public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name,
-                                                                         TypeSolver typeSolver) {
+  public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
     Preconditions.checkArgument(typeSolver != null);
 
     if (myDeclaration.hasVisibleField(name)) {
       return SymbolReference.solved(myDeclaration.getVisibleField(name));
     }
 
-    return getParent().solveSymbol(name, typeSolver);
+    return getParent().solveSymbol(name);
   }
 
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/BlockStmtContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/BlockStmtContext.java
new file mode 100644
index 0000000..2f1e284
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/BlockStmtContext.java
@@ -0,0 +1,51 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+public class BlockStmtContext extends AbstractJavaParserContext<BlockStmt> {
+
+    public BlockStmtContext(BlockStmt wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        int position = -1;
+        for (int i = 0; i < wrappedNode.getStatements().size(); i++) {
+            if (wrappedNode.getStatements().get(i).equals(child)) {
+                position = i;
+            }
+        }
+        if (position == -1) {
+            throw new RuntimeException();
+        }
+        List<VariableDeclarator> variableDeclarators = new LinkedList<>();
+        for (int i = position - 1; i >= 0; i--) {
+            variableDeclarators.addAll(localVariablesDeclaredIn(wrappedNode.getStatement(i)));
+        }
+        return variableDeclarators;
+    }
+
+    private List<VariableDeclarator> localVariablesDeclaredIn(Statement statement) {
+        if (statement instanceof ExpressionStmt) {
+            ExpressionStmt expressionStmt = (ExpressionStmt)statement;
+            if (expressionStmt.getExpression() instanceof VariableDeclarationExpr) {
+                VariableDeclarationExpr variableDeclarationExpr = (VariableDeclarationExpr)expressionStmt.getExpression();
+                List<VariableDeclarator> variableDeclarators = new LinkedList<>();
+                variableDeclarators.addAll(variableDeclarationExpr.getVariables());
+                return variableDeclarators;
+            }
+        }
+        return Collections.emptyList();
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java
index 4683f27..faa3410 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java
@@ -1,5 +1,8 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.ast.stmt.CatchClause;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
@@ -10,6 +13,7 @@
 import com.github.javaparser.symbolsolver.model.resolution.Value;
 import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
@@ -22,7 +26,7 @@
         super(wrappedNode, typeSolver);
     }
 
-    public final SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public final SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(wrappedNode.getParameter(), typeSolver);
         SymbolReference<? extends ResolvedValueDeclaration> symbolReference = AbstractJavaParserContext.solveWith(sb, name);
         if (symbolReference.isSolved()) {
@@ -30,25 +34,38 @@
         }
 
         // if nothing is found we should ask the parent context
-        return getParent().solveSymbol(name, typeSolver);
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public final Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public final Optional<Value> solveSymbolAsValue(String name) {
         SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(wrappedNode.getParameter(), typeSolver);
-        Optional<Value> symbolReference = solveWithAsValue(sb, name, typeSolver);
+        Optional<Value> symbolReference = solveWithAsValue(sb, name);
         if (symbolReference.isPresent()) {
             // Perform parameter type substitution as needed
             return symbolReference;
         }
 
         // if nothing is found we should ask the parent context
-        return getParent().solveSymbolAsValue(name, typeSolver);
+        return getParent().solveSymbolAsValue(name);
     }
 
     @Override
     public final SymbolReference<ResolvedMethodDeclaration> solveMethod(
-            String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+            String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
+    }
+
+    @Override
+    public List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<Parameter> parametersExposedToChild(Node child) {
+        if (child == getWrappedNode().getBody()) {
+            return Collections.singletonList(getWrappedNode().getParameter());
+        }
+        return Collections.emptyList();
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java
index 01f4b05..9cf888c 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java
@@ -16,17 +16,20 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.resolution.types.ResolvedTypeVariable;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.resolution.Value;
 
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
 
@@ -52,7 +55,7 @@
     ///
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         if (typeSolver == null) throw new IllegalArgumentException();
 
         if (this.getDeclaration().hasVisibleField(name)) {
@@ -60,11 +63,11 @@
         }
 
         // then to parent
-        return getParent().solveSymbol(name, typeSolver);
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public Optional<Value> solveSymbolAsValue(String name) {
         if (typeSolver == null) throw new IllegalArgumentException();
 
         if (this.getDeclaration().hasVisibleField(name)) {
@@ -72,31 +75,53 @@
         }
 
         // then to parent
-        return getParent().solveSymbolAsValue(name, typeSolver);
+        return getParent().solveSymbolAsValue(name);
     }
 
     @Override
-    public Optional<ResolvedType> solveGenericType(String name, TypeSolver typeSolver) {
+    public Optional<ResolvedType> solveGenericType(String name) {
         for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) {
             if (tp.getName().getId().equals(name)) {
                 return Optional.of(new ResolvedTypeVariable(new JavaParserTypeParameter(tp, typeSolver)));
             }
         }
-        return getParent().solveGenericType(name, typeSolver);
+        return getParent().solveGenericType(name);
     }
 
     @Override
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
-        return javaParserTypeDeclarationAdapter.solveType(name, typeSolver);
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+        // First attempt to resolve against implemented classes - cf. issue #2195
+        for (ClassOrInterfaceType implementedType : wrappedNode.getImplementedTypes()) {
+            if (implementedType.getName().getId().equals(name)) {
+                return JavaParserFactory.getContext(wrappedNode.getParentNode().orElse(null), typeSolver).solveType(name);
+            }
+        }
+
+        for (ClassOrInterfaceType extendedType : wrappedNode.getExtendedTypes()) {
+            if (extendedType.getName().getId().equals(name)) {
+                return JavaParserFactory.getContext(wrappedNode.getParentNode().orElse(null), typeSolver).solveType(name);
+            }
+        }
+
+        return javaParserTypeDeclarationAdapter.solveType(name);
     }
 
     @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly);
     }
 
-    public SymbolReference<ResolvedConstructorDeclaration> solveConstructor(List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
-        return javaParserTypeDeclarationAdapter.solveConstructor(argumentsTypes, typeSolver);
+    public SymbolReference<ResolvedConstructorDeclaration> solveConstructor(List<ResolvedType> argumentsTypes) {
+        return javaParserTypeDeclarationAdapter.solveConstructor(argumentsTypes);
+    }
+
+    @Override
+    public List<ResolvedFieldDeclaration> fieldsExposedToChild(Node child) {
+        List<ResolvedFieldDeclaration> fields = new LinkedList<>();
+        fields.addAll(this.wrappedNode.resolve().getDeclaredFields());
+        this.wrappedNode.getExtendedTypes().forEach(i -> fields.addAll(i.resolve().getAllFieldsVisibleToInheritors()));
+        this.wrappedNode.getImplementedTypes().forEach(i -> fields.addAll(i.resolve().getAllFieldsVisibleToInheritors()));
+        return fields;
     }
 
     ///
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
index e6a4aa0..e8943e0 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
@@ -18,27 +18,28 @@
 
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.ImportDeclaration;
+import com.github.javaparser.ast.Node;
 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.expr.MethodCallExpr;
 import com.github.javaparser.ast.expr.Name;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
 
+import java.util.LinkedList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author Federico Tomassetti
@@ -66,14 +67,14 @@
     ///
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
 
         // solve absolute references
         String itName = name;
         while (itName.contains(".")) {
             String typeName = getType(itName);
             String memberName = getMember(itName);
-            SymbolReference<ResolvedTypeDeclaration> type = this.solveType(typeName, typeSolver);
+            SymbolReference<ResolvedTypeDeclaration> type = this.solveType(typeName);
             if (type.isSolved()) {
                 return new SymbolSolver(typeSolver).solveSymbolInType(type.getCorrespondingDeclaration(), memberName);
             } else {
@@ -112,8 +113,11 @@
     }
 
     @Override
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+
         if (wrappedNode.getTypes() != null) {
+            // Look for types in this compilation unit. For instance, if the given name is "A", there may be a class or
+            // interface in this compilation unit called "A".
             for (TypeDeclaration<?> type : wrappedNode.getTypes()) {
                 if (type.getName().getId().equals(name)) {
                     if (type instanceof ClassOrInterfaceDeclaration) {
@@ -127,6 +131,44 @@
                     }
                 }
             }
+            // Look for member classes/interfaces of types in this compilation unit. For instance, if the given name is
+            // "A.B", there may be a class or interface in this compilation unit called "A" which has another member
+            // class or interface called "B". Since the type that we're looking for can be nested arbitrarily deeply
+            // ("A.B.C.D"), we look for the outermost type ("A" in the previous example) first, then recursively invoke
+            // this method for the remaining part of the given name.
+            if (name.indexOf('.') > -1) {
+                SymbolReference<ResolvedTypeDeclaration> ref = null;
+                SymbolReference<ResolvedTypeDeclaration> outerMostRef =
+                        solveType(name.substring(0, name.indexOf(".")));
+                if (outerMostRef != null && outerMostRef.isSolved() &&
+                    outerMostRef.getCorrespondingDeclaration() instanceof JavaParserClassDeclaration) {
+                    ref = ((JavaParserClassDeclaration) outerMostRef.getCorrespondingDeclaration())
+                                  .solveType(name.substring(name.indexOf(".") + 1));
+                } else if (outerMostRef != null && outerMostRef.isSolved() &&
+                           outerMostRef.getCorrespondingDeclaration() instanceof JavaParserInterfaceDeclaration) {
+                    ref = ((JavaParserInterfaceDeclaration) outerMostRef.getCorrespondingDeclaration())
+                                  .solveType(name.substring(name.indexOf(".") + 1));
+                }
+                if (ref != null && ref.isSolved()) {
+                    return ref;
+                }
+            }
+        }
+
+        // Look in current package
+        if (this.wrappedNode.getPackageDeclaration().isPresent()) {
+            String qName = this.wrappedNode.getPackageDeclaration().get().getName().toString() + "." + name;
+            SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+            if (ref != null && ref.isSolved()) {
+                return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+            }
+        } else {
+            // look for classes in the default package
+            String qName = name;
+            SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+            if (ref != null && ref.isSolved()) {
+                return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+            }
         }
 
         if (wrappedNode.getImports() != null) {
@@ -151,8 +193,10 @@
                     }
                     if (found) {
                         SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
-                        if (ref.isSolved()) {
+                        if (ref != null && ref.isSolved()) {
                             return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
+                        } else {
+                            return SymbolReference.unsolved(ResolvedTypeDeclaration.class);
                         }
                     }
                 }
@@ -162,32 +206,16 @@
                 if (importDecl.isAsterisk()) {
                     String qName = importDecl.getNameAsString() + "." + name;
                     SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
-                    if (ref.isSolved()) {
+                    if (ref != null && ref.isSolved()) {
                         return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
                     }
                 }
             }
         }
 
-        // Look in current package
-        if (this.wrappedNode.getPackageDeclaration().isPresent()) {
-            String qName = this.wrappedNode.getPackageDeclaration().get().getName().toString() + "." + name;
-            SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
-            if (ref.isSolved()) {
-                return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
-            }
-        } else {
-            // look for classes in the default package
-            String qName = name;
-            SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
-            if (ref.isSolved()) {
-                return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
-            }
-        }
-
         // Look in the java.lang package
         SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType("java.lang." + name);
-        if (ref.isSolved()) {
+        if (ref != null && ref.isSolved()) {
             return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
         }
 
@@ -230,10 +258,10 @@
     }
 
     @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
         for (ImportDeclaration importDecl : wrappedNode.getImports()) {
-            if(importDecl.isStatic()){
-                if(importDecl.isAsterisk()){
+            if (importDecl.isStatic()) {
+                if (importDecl.isAsterisk()) {
                     String importString = importDecl.getNameAsString();
 
                     if (this.wrappedNode.getPackageDeclaration().isPresent()
@@ -245,20 +273,22 @@
                     }
 
                     ResolvedTypeDeclaration ref = typeSolver.solveType(importString);
-                    SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver);
+                    SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true);
 
                     if (method.isSolved()) {
                         return method;
                     }
-                } else{
+                } else {
                     String qName = importDecl.getNameAsString();
 
                     if (qName.equals(name) || qName.endsWith("." + name)) {
                         String typeName = getType(qName);
                         ResolvedTypeDeclaration ref = typeSolver.solveType(typeName);
-                        SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver);
+                        SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true);
                         if (method.isSolved()) {
                             return method;
+                        } else {
+                            return SymbolReference.unsolved(ResolvedMethodDeclaration.class);
                         }
                     }
                 }
@@ -267,6 +297,24 @@
         return SymbolReference.unsolved(ResolvedMethodDeclaration.class);
     }
 
+    @Override
+    public List<ResolvedFieldDeclaration> fieldsExposedToChild(Node child) {
+        List<ResolvedFieldDeclaration> res = new LinkedList<>();
+        // Consider the static imports for static fields
+        for (ImportDeclaration importDeclaration : wrappedNode.getImports()) {
+            if (importDeclaration.isStatic()) {
+                Name typeNameAsNode = importDeclaration.isAsterisk() ? importDeclaration.getName() : importDeclaration.getName().getQualifier().get();
+                String typeName = typeNameAsNode.asString();
+                ResolvedReferenceTypeDeclaration typeDeclaration = typeSolver.solveType(typeName);
+                res.addAll(typeDeclaration.getAllFields().stream()
+                        .filter(f -> f.isStatic())
+                        .filter(f -> importDeclaration.isAsterisk() || importDeclaration.getName().getIdentifier().equals(f.getName()))
+                        .collect(Collectors.toList()));
+            }
+        }
+        return res;
+    }
+
     ///
     /// Private methods
     ///
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java
index bebaa73..0749021 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java
@@ -16,9 +16,14 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.ast.body.Parameter;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * @author Federico Tomassetti
  */
@@ -32,4 +37,12 @@
         super(wrappedNode, typeSolver);
     }
 
+    @Override
+    public List<Parameter> parametersExposedToChild(Node child) {
+        if (child == wrappedNode.getBody()) {
+            return wrappedNode.getParameters();
+        }
+        return Collections.emptyList();
+    }
+
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java
index e0eda24..0651d26 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java
@@ -20,17 +20,7 @@
 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
-import com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration;
-import com.github.javaparser.symbolsolver.javassistmodel.JavassistEnumDeclaration;
-import com.github.javaparser.symbolsolver.javassistmodel.JavassistInterfaceDeclaration;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionEnumDeclaration;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 
 import java.util.List;
 import java.util.Optional;
@@ -45,30 +35,14 @@
     }
 
     public static Optional<MethodUsage> solveMethodAsUsage(ResolvedTypeDeclaration typeDeclaration, String name,
-                                                           List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
-                                                           Context invokationContext, List<ResolvedType> typeParameters) {
-        if (typeDeclaration instanceof JavassistClassDeclaration) {
-            return ((JavassistClassDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
-        } else if (typeDeclaration instanceof JavassistInterfaceDeclaration) {
-            return ((JavassistInterfaceDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
-        } else if (typeDeclaration instanceof JavassistEnumDeclaration) {
-            return ((JavassistEnumDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
-        } else if (typeDeclaration instanceof ReflectionClassDeclaration) {
-            return ((ReflectionClassDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
-        } else if (typeDeclaration instanceof ReflectionInterfaceDeclaration) {
-            return ((ReflectionInterfaceDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
-        } else if (typeDeclaration instanceof ReflectionEnumDeclaration) {
-            return ((ReflectionEnumDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
-        } else if (typeDeclaration instanceof JavaParserClassDeclaration) {
-            return ((JavaParserClassDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver);
-        } else if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
-            return ((JavaParserInterfaceDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver);
-        } else if (typeDeclaration instanceof JavaParserEnumDeclaration) {
-            return ((JavaParserEnumDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver);
-        } else if (typeDeclaration instanceof JavaParserAnonymousClassDeclaration) {
-            return ((JavaParserAnonymousClassDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver);
-        }
-        throw new UnsupportedOperationException(typeDeclaration.toString());
-    }
+                                                           List<ResolvedType> argumentsTypes, Context invokationContext,
+                                                           List<ResolvedType> typeParameters) {
 
+        if (typeDeclaration instanceof MethodUsageResolutionCapability) {
+            return ((MethodUsageResolutionCapability) typeDeclaration)
+                           .solveMethodAsUsage(name, argumentsTypes, invokationContext, typeParameters);
+        } else {
+            throw new UnsupportedOperationException(typeDeclaration.toString());
+        }
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java
index 7f2365f..92582e8 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         if (typeSolver == null) throw new IllegalArgumentException();
 
         // among constants
@@ -59,17 +59,17 @@
         }
 
         // then to parent
-        return getParent().solveSymbol(name, typeSolver);
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
-        return javaParserTypeDeclarationAdapter.solveType(name, typeSolver);
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+        return javaParserTypeDeclarationAdapter.solveType(name);
     }
 
     @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly);
     }
 
     ///
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java
index 65ccedf..1e6534c 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java
@@ -19,11 +19,7 @@
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.expr.FieldAccessExpr;
 import com.github.javaparser.ast.expr.ThisExpr;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
+import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
@@ -37,7 +33,6 @@
 import java.util.List;
 import java.util.Optional;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
 
 /**
@@ -52,28 +47,28 @@
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         if (wrappedNode.getName().toString().equals(name)) {
             if (wrappedNode.getScope() instanceof ThisExpr) {
                 ResolvedType typeOfThis = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode);
                 return new SymbolSolver(typeSolver).solveSymbolInType(typeOfThis.asReferenceType().getTypeDeclaration(), name);
             }
         }
-        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveSymbol(name, typeSolver);
+        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveSymbol(name);
     }
 
     @Override
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
-        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveType(name, typeSolver);
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveType(name);
     }
 
     @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveMethod(name, parameterTypes, false, typeSolver);
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes, boolean staticOnly) {
+        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveMethod(name, parameterTypes, false);
     }
 
     @Override
-    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public Optional<Value> solveSymbolAsValue(String name) {
         Expression scope = wrappedNode.getScope();
         if (wrappedNode.getName().toString().equals(name)) {
             ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getType(scope);
@@ -81,19 +76,31 @@
                 return Optional.of(new Value(ResolvedPrimitiveType.INT, ARRAY_LENGTH_FIELD_NAME));
             }
             if (typeOfScope.isReferenceType()) {
+                if (typeOfScope.asReferenceType().getTypeDeclaration().isEnum()) {
+                    ResolvedEnumDeclaration enumDeclaration = (ResolvedEnumDeclaration)typeOfScope.asReferenceType().getTypeDeclaration();
+                    if (enumDeclaration.hasEnumConstant(name)) {
+                        return Optional.of(new Value(enumDeclaration.getEnumConstant(name).getType(), name));
+                    }
+                }
                 Optional<ResolvedType> typeUsage = typeOfScope.asReferenceType().getFieldType(name);
                 return typeUsage.map(resolvedType -> new Value(resolvedType, name));
             } else {
                 return Optional.empty();
             }
         } else {
-            return getParent().solveSymbolAsValue(name, typeSolver);
+            return getParent().solveSymbolAsValue(name);
         }
     }
 
-    public SymbolReference<ResolvedFieldDeclaration> solveField(String name, TypeSolver typeSolver) {
-        Collection<ResolvedReferenceTypeDeclaration> rrtds = findTypeDeclarations(Optional.of(wrappedNode.getScope()), typeSolver);
+    public SymbolReference<ResolvedValueDeclaration> solveField(String name) {
+        Collection<ResolvedReferenceTypeDeclaration> rrtds = findTypeDeclarations(Optional.of(wrappedNode.getScope()));
         for (ResolvedReferenceTypeDeclaration rrtd : rrtds) {
+            if (rrtd.isEnum()) {
+                Optional<ResolvedEnumConstantDeclaration> enumConstant = rrtd.asEnum().getEnumConstants().stream().filter(c -> c.getName().equals(name)).findFirst();
+                if (enumConstant.isPresent()) {
+                    return SymbolReference.solved(enumConstant.get());
+                }
+            }
             try {
                 return SymbolReference.solved(rrtd.getField(wrappedNode.getName().getId()));
             } catch (Throwable t) {
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForEachStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForEachStatementContext.java
new file mode 100644
index 0000000..4bb7b40
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForEachStatementContext.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ForEachStmt;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
+
+public class ForEachStatementContext extends AbstractJavaParserContext<ForEachStmt> {
+
+    public ForEachStatementContext(ForEachStmt wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
+        if (wrappedNode.getVariable().getVariables().size() != 1) {
+            throw new IllegalStateException();
+        }
+        VariableDeclarator variableDeclarator = wrappedNode.getVariable().getVariables().get(0);
+        if (variableDeclarator.getName().getId().equals(name)) {
+            return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver));
+        } else {
+            if (requireParentNode(wrappedNode) instanceof BlockStmt) {
+                return StatementContext.solveInBlock(name, typeSolver, wrappedNode);
+            } else {
+                return getParent().solveSymbol(name);
+            }
+        }
+    }
+
+    @Override
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
+                                                                  boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
+    }
+
+    @Override
+    public List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        if (child == wrappedNode.getBody()) {
+            return wrappedNode.getVariable().getVariables();
+        }
+        return Collections.emptyList();
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java
index cf3fe3b..a758ca6 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java
@@ -16,6 +16,7 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.ast.expr.AssignExpr;
 import com.github.javaparser.ast.expr.Expression;
@@ -30,6 +31,7 @@
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
+import java.util.LinkedList;
 import java.util.List;
 
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
@@ -41,7 +43,7 @@
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         for (Expression expression : wrappedNode.getInitialization()) {
             if (expression instanceof VariableDeclarationExpr) {
                 VariableDeclarationExpr variableDeclarationExpr = (VariableDeclarationExpr) expression;
@@ -58,13 +60,25 @@
         if (requireParentNode(wrappedNode) instanceof NodeWithStatements) {
             return StatementContext.solveInBlock(name, typeSolver, wrappedNode);
         } else {
-            return getParent().solveSymbol(name, typeSolver);
+            return getParent().solveSymbol(name);
         }
     }
 
     @Override
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
-                                                                  boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+                                                                  boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
+    }
+
+    @Override
+    public List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        List<VariableDeclarator> res = new LinkedList<>();
+        for (Expression expression : wrappedNode.getInitialization()) {
+            if (expression instanceof VariableDeclarationExpr) {
+                VariableDeclarationExpr variableDeclarationExpr = (VariableDeclarationExpr) expression;
+                res.addAll(variableDeclarationExpr.getVariables());
+            }
+        }
+        return res;
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java
deleted file mode 100644
index ba41202..0000000
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
-
-import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.stmt.BlockStmt;
-import com.github.javaparser.ast.stmt.ForeachStmt;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
-import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-
-import java.util.List;
-
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
-
-public class ForechStatementContext extends AbstractJavaParserContext<ForeachStmt> {
-
-    public ForechStatementContext(ForeachStmt wrappedNode, TypeSolver typeSolver) {
-        super(wrappedNode, typeSolver);
-    }
-
-    @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
-        if (wrappedNode.getVariable().getVariables().size() != 1) {
-            throw new IllegalStateException();
-        }
-        VariableDeclarator variableDeclarator = wrappedNode.getVariable().getVariables().get(0);
-        if (variableDeclarator.getName().getId().equals(name)) {
-            return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver));
-        } else {
-            if (requireParentNode(wrappedNode) instanceof BlockStmt) {
-                return StatementContext.solveInBlock(name, typeSolver, wrappedNode);
-            } else {
-                return getParent().solveSymbol(name, typeSolver);
-            }
-        }
-    }
-
-    @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
-                                                                  boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
-    }
-}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
index 993f42d..e1267d5 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
@@ -1,5 +1,6 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.body.BodyDeclaration;
 import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters;
 import com.github.javaparser.ast.type.TypeParameter;
@@ -12,7 +13,7 @@
 import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.reflectionmodel.*;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic;
 import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
 
@@ -38,7 +39,7 @@
         this.context = context;
     }
 
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
         if (this.wrappedNode.getName().getId().equals(name)) {
             return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(wrappedNode));
         }
@@ -50,9 +51,9 @@
                 if (internalType.getName().getId().equals(name)) {
                     return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType));
                 } else if (name.startsWith(String.format("%s.%s", wrappedNode.getName(), internalType.getName()))) {
-                    return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(wrappedNode.getName().getId().length() + 1), typeSolver);
+                    return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(wrappedNode.getName().getId().length() + 1));
                 } else if (name.startsWith(String.format("%s.", internalType.getName()))) {
-                    return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver);
+                    return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1));
                 }
             }
         }
@@ -68,46 +69,75 @@
         }
 
         // Look into extended classes and implemented interfaces
-        for (ResolvedReferenceType ancestor : this.typeDeclaration.getAncestors()) {
-        	try {
-	            for (ResolvedTypeDeclaration internalTypeDeclaration : ancestor.getTypeDeclaration().internalTypes()) {
-	                if (internalTypeDeclaration.getName().equals(name)) {
-	                    return SymbolReference.solved(internalTypeDeclaration);
-	                }
-	            }
-        	} catch (UnsupportedOperationException e) {
-	            // just continue using the next ancestor
-            }
-        }
-
-        return context.getParent().solveType(name, typeSolver);
+        ResolvedTypeDeclaration type = checkAncestorsForType(name, this.typeDeclaration);
+        return ((type != null) ? SymbolReference.solved(type) : context.getParent().solveType(name));
     }
 
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+    /**
+     * Recursively checks the ancestors of the {@param declaration} if an internal type is declared with a name equal
+     * to {@param name}.
+     * @return A ResolvedTypeDeclaration matching the {@param name}, null otherwise
+     */
+    private ResolvedTypeDeclaration checkAncestorsForType(String name, ResolvedReferenceTypeDeclaration declaration) {
+        for (ResolvedReferenceType ancestor : declaration.getAncestors(true)) {
+            try {
+                for (ResolvedTypeDeclaration internalTypeDeclaration : ancestor.getTypeDeclaration().internalTypes()) {
+                    boolean visible = true;
+                    if (internalTypeDeclaration instanceof ResolvedReferenceTypeDeclaration) {
+                        ResolvedReferenceTypeDeclaration resolvedReferenceTypeDeclaration = internalTypeDeclaration.asReferenceType();
+                        if (resolvedReferenceTypeDeclaration instanceof HasAccessSpecifier) {
+                            visible = ((HasAccessSpecifier) resolvedReferenceTypeDeclaration).accessSpecifier() != AccessSpecifier.PRIVATE;
+                        }
+                    }
+                    if (internalTypeDeclaration.getName().equals(name)) {
+                        if (visible) {
+                            return internalTypeDeclaration;
+                        } else {
+                            return null;
+                        }
+                    }
+                }
+                // check recursively the ancestors of this ancestor
+                ResolvedTypeDeclaration ancestorDeclaration = checkAncestorsForType(name, ancestor.getTypeDeclaration());
+                if (ancestorDeclaration != null) {
+                    return ancestorDeclaration;
+                }
+            } catch (UnsupportedOperationException e) {
+                // just continue using the next ancestor
+            }
+        }
+        return null;
+    }
+
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
         List<ResolvedMethodDeclaration> candidateMethods = typeDeclaration.getDeclaredMethods().stream()
                 .filter(m -> m.getName().equals(name))
-                .filter(m -> !staticOnly || (staticOnly &&  m.isStatic()))
+                .filter(m -> !staticOnly || m.isStatic())
                 .collect(Collectors.toList());
         // We want to avoid infinite recursion in case of Object having Object as ancestor
         if (!Object.class.getCanonicalName().equals(typeDeclaration.getQualifiedName())) {
-            for (ResolvedReferenceType ancestor : typeDeclaration.getAncestors()) {
-		// Avoid recursion on self
+            for (ResolvedReferenceType ancestor : typeDeclaration.getAncestors(true)) {
+                // Avoid recursion on self
                 if (typeDeclaration != ancestor.getTypeDeclaration()) {
+                    candidateMethods.addAll(ancestor.getAllMethodsVisibleToInheritors()
+                            .stream()
+                            .filter(m -> m.getName().equals(name))
+                            .collect(Collectors.toList()));
                     SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic
-                            .solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver);
+                            .solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly);
                     // consider methods from superclasses and only default methods from interfaces :
                     // not true, we should keep abstract as a valid candidate
                     // abstract are removed in MethodResolutionLogic.isApplicable is necessary
                     if (res.isSolved()) {
                         candidateMethods.add(res.getCorrespondingDeclaration());
                     }
-		}
+                }
             }
         }
         // We want to avoid infinite recursion when a class is using its own method
         // see issue #75
         if (candidateMethods.isEmpty()) {
-            SymbolReference<ResolvedMethodDeclaration> parentSolution = context.getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> parentSolution = context.getParent().solveMethod(name, argumentsTypes, staticOnly);
             if (parentSolution.isSolved()) {
                 candidateMethods.add(parentSolution.getCorrespondingDeclaration());
             }
@@ -115,7 +145,7 @@
 
         // if is interface and candidate method list is empty, we should check the Object Methods
         if (candidateMethods.isEmpty() && typeDeclaration.isInterface()) {
-            SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false);
             if (res.isSolved()) {
                 candidateMethods.add(res.getCorrespondingDeclaration());
             }
@@ -124,9 +154,9 @@
         return MethodResolutionLogic.findMostApplicable(candidateMethods, name, argumentsTypes, typeSolver);
     }
 
-    public SymbolReference<ResolvedConstructorDeclaration> solveConstructor(List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
+    public SymbolReference<ResolvedConstructorDeclaration> solveConstructor(List<ResolvedType> argumentsTypes) {
         if (typeDeclaration instanceof ResolvedClassDeclaration) {
-            return ConstructorResolutionLogic.findMostApplicable(((ResolvedClassDeclaration) typeDeclaration).getConstructors(), argumentsTypes, typeSolver);
+            return ConstructorResolutionLogic.findMostApplicable(typeDeclaration.getConstructors(), argumentsTypes, typeSolver);
         }
         return SymbolReference.unsolved(ResolvedConstructorDeclaration.class);
     }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java
index 3c34fac..82bfa74 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java
@@ -16,6 +16,7 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.Parameter;
 import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.ast.expr.Expression;
@@ -53,7 +54,7 @@
     }
 
     @Override
-    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public Optional<Value> solveSymbolAsValue(String name) {
         for (Parameter parameter : wrappedNode.getParameters()) {
             SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
             int index = 0;
@@ -134,11 +135,11 @@
         }
 
         // if nothing is found we should ask the parent context
-        return getParent().solveSymbolAsValue(name, typeSolver);
+        return getParent().solveSymbolAsValue(name);
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         for (Parameter parameter : wrappedNode.getParameters()) {
             SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
             SymbolReference<ResolvedValueDeclaration> symbolReference = solveWith(sb, name);
@@ -148,25 +149,33 @@
         }
 
         // if nothing is found we should ask the parent context
-        return getParent().solveSymbol(name, typeSolver);
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
-        return getParent().solveType(name, typeSolver);
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+        return getParent().solveType(name);
     }
 
     @Override
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(
-            String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+            String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
+    }
+
+    @Override
+    public List<Parameter> parametersExposedToChild(Node child) {
+        if (child == wrappedNode.getBody()) {
+            return wrappedNode.getParameters();
+        }
+        return Collections.emptyList();
     }
 
     ///
     /// Protected methods
     ///
 
-    protected final Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) {
+    protected final Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, String name) {
         for (ResolvedValueDeclaration decl : symbolDeclarator.getSymbolDeclarations()) {
             if (decl.getName().equals(name)) {
 
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java
index ca9f07c..350b1f8 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java
@@ -55,7 +55,7 @@
     ///
 
     @Override
-    public Optional<ResolvedType> solveGenericType(String name, TypeSolver typeSolver) {
+    public Optional<ResolvedType> solveGenericType(String name) {
         if(wrappedNode.getScope().isPresent()){
             ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getType(wrappedNode.getScope().get());
             Optional<ResolvedType> res = typeOfScope.asReferenceType().getGenericParameterByName(name);
@@ -71,15 +71,15 @@
     }
 
     @Override
-    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes) {
         if (wrappedNode.getScope().isPresent()) {
             Expression scope = wrappedNode.getScope().get();
             // Consider static method calls
             if (scope instanceof NameExpr) {
                 String className = ((NameExpr) scope).getName().getId();
-                SymbolReference<ResolvedTypeDeclaration> ref = solveType(className, typeSolver);
+                SymbolReference<ResolvedTypeDeclaration> ref = solveType(className);
                 if (ref.isSolved()) {
-                    SymbolReference<ResolvedMethodDeclaration> m = MethodResolutionLogic.solveMethodInType(ref.getCorrespondingDeclaration(), name, argumentsTypes, typeSolver);
+                    SymbolReference<ResolvedMethodDeclaration> m = MethodResolutionLogic.solveMethodInType(ref.getCorrespondingDeclaration(), name, argumentsTypes);
                     if (m.isSolved()) {
                         MethodUsage methodUsage = new MethodUsage(m.getCorrespondingDeclaration());
                         methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage);
@@ -108,13 +108,13 @@
                 argumentsTypes.set(i, updatedArgumentType);
             }
 
-            return solveMethodAsUsage(typeOfScope, name, argumentsTypes, typeSolver, this);
+            return solveMethodAsUsage(typeOfScope, name, argumentsTypes, this);
         } else {
             Context parentContext = getParent();
-            while (parentContext instanceof MethodCallExprContext) {
+            while (parentContext instanceof MethodCallExprContext || parentContext instanceof ObjectCreationContext) {
                 parentContext = parentContext.getParent();
             }
-            return parentContext.solveMethodAsUsage(name, argumentsTypes, typeSolver);
+            return parentContext.solveMethodAsUsage(name, argumentsTypes);
         }
     }
 
@@ -137,21 +137,21 @@
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
-        return getParent().solveSymbol(name, typeSolver);
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public Optional<Value> solveSymbolAsValue(String name) {
         Context parentContext = getParent();
-        return parentContext.solveSymbolAsValue(name, typeSolver);
+        return parentContext.solveSymbolAsValue(name);
     }
 
     @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        Collection<ResolvedReferenceTypeDeclaration> rrtds = findTypeDeclarations(wrappedNode.getScope(), typeSolver);
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        Collection<ResolvedReferenceTypeDeclaration> rrtds = findTypeDeclarations(wrappedNode.getScope());
         for (ResolvedReferenceTypeDeclaration rrtd : rrtds) {
-            SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic.solveMethodInType(rrtd, name, argumentsTypes, false, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic.solveMethodInType(rrtd, name, argumentsTypes, false);
             if (res.isSolved()) {
                 return res;
             }
@@ -164,9 +164,9 @@
     ///
 
     private Optional<MethodUsage> solveMethodAsUsage(ResolvedReferenceType refType, String name,
-                                                     List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
+                                                     List<ResolvedType> argumentsTypes,
                                                      Context invokationContext) {
-        Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(refType.getTypeDeclaration(), name, argumentsTypes, typeSolver, invokationContext, refType.typeParametersValues());
+        Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(refType.getTypeDeclaration(), name, argumentsTypes, invokationContext, refType.typeParametersValues());
         if (ref.isPresent()) {
             MethodUsage methodUsage = ref.get();
 
@@ -255,6 +255,12 @@
             mappings.put(target.asTypeParameter(), source);
             return;
         }
+        if (source.isArray() && target.isArray()) {
+            ResolvedType sourceComponentType = source.asArrayType().getComponentType();
+            ResolvedType targetComponentType = target.asArrayType().getComponentType();
+            inferTypes(sourceComponentType, targetComponentType, mappings);
+            return;
+        }
         if (source.isArray() && target.isWildcard()){
             if(target.asWildcard().isBounded()){
                 inferTypes(source, target.asWildcard().getBoundedType(), mappings);
@@ -351,12 +357,13 @@
             }
             matchedTypeParameters.put(expectedType.asTypeParameter(), actualType);
         } else if (expectedType.isArray()) {
-            if (!actualType.isArray()) {
+        	// Issue 2258 : NullType must not fail this search
+            if (!(actualType.isArray() || actualType.isNull())) {
                 throw new UnsupportedOperationException(actualType.getClass().getCanonicalName());
             }
             matchTypeParameters(
                     expectedType.asArrayType().getComponentType(),
-                    actualType.asArrayType().getComponentType(),
+                    actualType.isNull() ? actualType : actualType.asArrayType().getComponentType(),
                     matchedTypeParameters);
         } else if (expectedType.isReferenceType()) {
             // avoid cases where the actual type has no type parameters but the expected one has. Such as: "classX extends classY<Integer>"
@@ -376,9 +383,9 @@
         }
     }
 
-    private Optional<MethodUsage> solveMethodAsUsage(ResolvedTypeVariable tp, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, Context invokationContext) {
+    private Optional<MethodUsage> solveMethodAsUsage(ResolvedTypeVariable tp, String name, List<ResolvedType> argumentsTypes, Context invokationContext) {
         for (ResolvedTypeParameterDeclaration.Bound bound : tp.asTypeParameter().getBounds()) {
-            Optional<MethodUsage> methodUsage = solveMethodAsUsage(bound.getType(), name, argumentsTypes, typeSolver, invokationContext);
+            Optional<MethodUsage> methodUsage = solveMethodAsUsage(bound.getType(), name, argumentsTypes, invokationContext);
             if (methodUsage.isPresent()) {
                 return methodUsage;
             }
@@ -386,26 +393,33 @@
         return Optional.empty();
     }
 
-    private Optional<MethodUsage> solveMethodAsUsage(ResolvedType type, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, Context invokationContext) {
+    private Optional<MethodUsage> solveMethodAsUsage(ResolvedType type, String name, List<ResolvedType> argumentsTypes, Context invokationContext) {
         if (type instanceof ResolvedReferenceType) {
-            return solveMethodAsUsage((ResolvedReferenceType) type, name, argumentsTypes, typeSolver, invokationContext);
+            return solveMethodAsUsage((ResolvedReferenceType) type, name, argumentsTypes, invokationContext);
         } else if (type instanceof ResolvedTypeVariable) {
-            return solveMethodAsUsage((ResolvedTypeVariable) type, name, argumentsTypes, typeSolver, invokationContext);
+            return solveMethodAsUsage((ResolvedTypeVariable) type, name, argumentsTypes, invokationContext);
         } else if (type instanceof ResolvedWildcard) {
             ResolvedWildcard wildcardUsage = (ResolvedWildcard) type;
             if (wildcardUsage.isSuper()) {
-                return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, argumentsTypes, typeSolver, invokationContext);
+                return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, argumentsTypes, invokationContext);
             } else if (wildcardUsage.isExtends()) {
-                throw new UnsupportedOperationException("extends wildcard");
+                return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, argumentsTypes, invokationContext);
             } else {
-                throw new UnsupportedOperationException("unbounded wildcard");
+                return solveMethodAsUsage(new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver), name, argumentsTypes, invokationContext);
             }
         } else if (type instanceof ResolvedLambdaConstraintType){
             ResolvedLambdaConstraintType constraintType = (ResolvedLambdaConstraintType) type;
-            return solveMethodAsUsage(constraintType.getBound(), name, argumentsTypes, typeSolver, invokationContext);
+            return solveMethodAsUsage(constraintType.getBound(), name, argumentsTypes, invokationContext);
         } else if (type instanceof ResolvedArrayType) {
             // An array inherits methods from Object not from it's component type
-            return solveMethodAsUsage(new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver), name, argumentsTypes, typeSolver, invokationContext);
+            return solveMethodAsUsage(new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver), name, argumentsTypes, invokationContext);
+        } else if (type instanceof ResolvedUnionType) {
+            Optional<ResolvedReferenceType> commonAncestor = type.asUnionType().getCommonAncestor();
+            if (commonAncestor.isPresent()) {
+                return solveMethodAsUsage(commonAncestor.get(), name, argumentsTypes, invokationContext);
+            } else {
+                throw new UnsupportedOperationException("no common ancestor available for " + type.describe());
+            }
         } else {
             throw new UnsupportedOperationException("type usage: " + type.getClass().getCanonicalName());
         }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java
index 9a7530b..b8bd2ce 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java
@@ -16,9 +16,14 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.Parameter;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * @author Federico Tomassetti
  */
@@ -32,4 +37,12 @@
         super(wrappedNode, typeSolver);
     }
 
+
+    @Override
+    public List<Parameter> parametersExposedToChild(Node child) {
+        if (wrappedNode.getBody().isPresent() && child == wrappedNode.getBody().get()) {
+            return wrappedNode.getParameters();
+        }
+        return Collections.emptyList();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ObjectCreationContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ObjectCreationContext.java
new file mode 100644
index 0000000..0dc8658
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ObjectCreationContext.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.List;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ObjectCreationContext extends AbstractJavaParserContext<ObjectCreationExpr> {
+
+    public ObjectCreationContext(ObjectCreationExpr wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+        if (wrappedNode.getScope().isPresent()) {
+            Expression scope = wrappedNode.getScope().get();
+            ResolvedType scopeType = JavaParserFacade.get(typeSolver).getType(scope);
+            if (scopeType.isReferenceType()) {
+                ResolvedReferenceType referenceType = scopeType.asReferenceType();
+                for (ResolvedTypeDeclaration it : referenceType.getTypeDeclaration().internalTypes()) {
+                    if (it.getName().equals(name)) {
+                        return SymbolReference.solved(it);
+                    }
+                }
+            }
+            throw new UnsolvedSymbolException("Unable to solve qualified object creation expression in the context of expression of type " + scopeType.describe());
+        }
+        // find first parent node that is not an object creation expression to avoid stack overflow errors, see #1711
+        Node parentNode = requireParentNode(wrappedNode);
+        while (parentNode instanceof ObjectCreationExpr) {
+            parentNode = requireParentNode(parentNode);
+        }
+        return JavaParserFactory.getContext(parentNode, typeSolver).solveType(name);
+    }
+
+    @Override
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
+        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveSymbol(name);
+    }
+
+    @Override
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveMethod(name, argumentsTypes, false);
+    }
+
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java
index 8acab7a..951ef18 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java
@@ -68,7 +68,7 @@
         }
 
         // if nothing is found we should ask the parent context
-        return JavaParserFactory.getContext(requireParentNode(stmt), typeSolver).solveSymbol(name, typeSolver);
+        return JavaParserFactory.getContext(requireParentNode(stmt), typeSolver).solveSymbol(name);
     }
 
     public static Optional<Value> solveInBlockAsValue(String name, TypeSolver typeSolver, Statement stmt) {
@@ -94,31 +94,31 @@
         }
 
         // if nothing is found we should ask the parent context
-        return JavaParserFactory.getContext(requireParentNode(stmt), typeSolver).solveSymbolAsValue(name, typeSolver);
+        return JavaParserFactory.getContext(requireParentNode(stmt), typeSolver).solveSymbolAsValue(name);
     }
 
     @Override
-    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public Optional<Value> solveSymbolAsValue(String name) {
 
         // if we're in a multiple Variable declaration line (for ex: double a=0, b=a;)
         SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver);
-        Optional<Value> symbolReference = solveWithAsValue(symbolDeclarator, name, typeSolver);
+        Optional<Value> symbolReference = solveWithAsValue(symbolDeclarator, name);
         if (symbolReference.isPresent()) {
             return symbolReference;
         }
 
         // we should look in all the statements preceding, treating them as SymbolDeclarators
         if (requireParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) {
-            return getParent().solveSymbolAsValue(name, typeSolver);
+            return getParent().solveSymbolAsValue(name);
         }
         if (requireParentNode(wrappedNode) instanceof LambdaExpr) {
-            return getParent().solveSymbolAsValue(name, typeSolver);
+            return getParent().solveSymbolAsValue(name);
         }
         if (requireParentNode(wrappedNode) instanceof IfStmt) {
-            return getParent().solveSymbolAsValue(name, typeSolver);
+            return getParent().solveSymbolAsValue(name);
         }
         if (!(requireParentNode(wrappedNode) instanceof NodeWithStatements)) {
-            return getParent().solveSymbolAsValue(name, typeSolver);
+            return getParent().solveSymbolAsValue(name);
         }
         NodeWithStatements<?> nodeWithStmt = (NodeWithStatements<?>) requireParentNode(wrappedNode);
         int position = -1;
@@ -132,7 +132,7 @@
         }
         for (int i = position - 1; i >= 0; i--) {
             symbolDeclarator = JavaParserFactory.getSymbolDeclarator(nodeWithStmt.getStatements().get(i), typeSolver);
-            symbolReference = solveWithAsValue(symbolDeclarator, name, typeSolver);
+            symbolReference = solveWithAsValue(symbolDeclarator, name);
             if (symbolReference.isPresent()) {
                 return symbolReference;
             }
@@ -140,11 +140,11 @@
 
         // if nothing is found we should ask the parent context
         Context parentContext = getParent();
-        return parentContext.solveSymbolAsValue(name, typeSolver);
+        return parentContext.solveSymbolAsValue(name);
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
 
         // if we're in a multiple Variable declaration line (for ex: double a=0, b=a;)
         SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver);
@@ -155,16 +155,16 @@
 
         // we should look in all the statements preceding, treating them as SymbolDeclarators
         if (requireParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) {
-            return getParent().solveSymbol(name, typeSolver);
+            return getParent().solveSymbol(name);
         }
         if (requireParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.ConstructorDeclaration) {
-            return getParent().solveSymbol(name, typeSolver);
+            return getParent().solveSymbol(name);
         }
         if (requireParentNode(wrappedNode) instanceof LambdaExpr) {
-            return getParent().solveSymbol(name, typeSolver);
+            return getParent().solveSymbol(name);
         }
         if (!(requireParentNode(wrappedNode) instanceof NodeWithStatements)) {
-            return getParent().solveSymbol(name, typeSolver);
+            return getParent().solveSymbol(name);
         }
         NodeWithStatements<?> nodeWithStmt = (NodeWithStatements<?>) requireParentNode(wrappedNode);
         int position = -1;
@@ -185,16 +185,16 @@
         }
 
         // if nothing is found we should ask the parent context
-        return getParent().solveSymbol(name, typeSolver);
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
     }
 
     @Override
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
-        return getParent().solveType(name, typeSolver);
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+        return getParent().solveType(name);
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java
index 1596729..4cd84f3 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java
@@ -17,7 +17,7 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
 import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.ast.stmt.SwitchEntryStmt;
+import com.github.javaparser.ast.stmt.SwitchEntry;
 import com.github.javaparser.ast.stmt.SwitchStmt;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
@@ -36,19 +36,22 @@
 /**
  * @author Federico Tomassetti
  */
-public class SwitchEntryContext extends AbstractJavaParserContext<SwitchEntryStmt> {
+public class SwitchEntryContext extends AbstractJavaParserContext<SwitchEntry> {
 
-    public SwitchEntryContext(SwitchEntryStmt wrappedNode, TypeSolver typeSolver) {
+    public SwitchEntryContext(SwitchEntry wrappedNode, TypeSolver typeSolver) {
         super(wrappedNode, typeSolver);
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         SwitchStmt switchStmt = (SwitchStmt) requireParentNode(wrappedNode);
         ResolvedType type = JavaParserFacade.get(typeSolver).getType(switchStmt.getSelector());
         if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isEnum()) {
             if (type instanceof ReferenceTypeImpl) {
                 ReferenceTypeImpl typeUsageOfTypeDeclaration = (ReferenceTypeImpl) type;
+                if (typeUsageOfTypeDeclaration.getTypeDeclaration().asEnum().hasEnumConstant(name)) {
+                    return SymbolReference.solved(typeUsageOfTypeDeclaration.getTypeDeclaration().asEnum().getEnumConstant(name));
+                }
                 if (typeUsageOfTypeDeclaration.getTypeDeclaration().hasField(name)) {
                     return SymbolReference.solved(typeUsageOfTypeDeclaration.getTypeDeclaration().getField(name));
                 }
@@ -57,24 +60,26 @@
             }
         }
 
-        // look for declaration in other switch statements
-        for (SwitchEntryStmt seStmt : switchStmt.getEntries()) {
-            if (!seStmt.equals(wrappedNode)) {
-                for (Statement stmt : seStmt.getStatements()) {
-                    SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(stmt, typeSolver);
-                    SymbolReference<? extends ResolvedValueDeclaration> symbolReference = solveWith(symbolDeclarator, name);
-                    if (symbolReference.isSolved()) {
-                        return symbolReference;
-                    }
+        // look for declaration in this and previous switch entry statements
+        for (SwitchEntry seStmt : switchStmt.getEntries()) {
+            for (Statement stmt : seStmt.getStatements()) {
+                SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(stmt, typeSolver);
+                SymbolReference<? extends ResolvedValueDeclaration> symbolReference = solveWith(symbolDeclarator, name);
+                if (symbolReference.isSolved()) {
+                    return symbolReference;
                 }
             }
+            // once we reach this switch entry statement, stop: we do not want to look in later switch entry statements
+            if (seStmt == wrappedNode) {
+                break;
+            }
         }
 
-        return getParent().solveSymbol(name, typeSolver);
+        return getParent().solveSymbol(name);
     }
 
     @Override
-    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java
index 80932e5..345e2e6 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java
@@ -16,6 +16,8 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
 
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.expr.VariableDeclarationExpr;
@@ -29,10 +31,12 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.resolution.Value;
 
+import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
 
 public class TryWithResourceContext extends AbstractJavaParserContext<TryStmt> {
@@ -42,7 +46,7 @@
     }
 
     @Override
-    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+    public Optional<Value> solveSymbolAsValue(String name) {
         for (Expression expr : wrappedNode.getResources()) {
             if (expr instanceof VariableDeclarationExpr) {
                 for (VariableDeclarator v : ((VariableDeclarationExpr)expr).getVariables()) {
@@ -57,12 +61,12 @@
         if (requireParentNode(wrappedNode) instanceof BlockStmt) {
             return StatementContext.solveInBlockAsValue(name, typeSolver, wrappedNode);
         } else {
-            return getParent().solveSymbolAsValue(name, typeSolver);
+            return getParent().solveSymbolAsValue(name);
         }
     }
 
     @Override
-    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+    public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name) {
         for (Expression expr : wrappedNode.getResources()) {
             if (expr instanceof VariableDeclarationExpr) {
                 for (VariableDeclarator v : ((VariableDeclarationExpr)expr).getVariables()) {
@@ -76,13 +80,37 @@
         if (requireParentNode(wrappedNode) instanceof BlockStmt) {
             return StatementContext.solveInBlock(name, typeSolver, wrappedNode);
         } else {
-            return getParent().solveSymbol(name, typeSolver);
+            return getParent().solveSymbol(name);
         }
     }
 
     @Override
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
-                                                                  boolean staticOnly, TypeSolver typeSolver) {
-        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+                                                                  boolean staticOnly) {
+        return getParent().solveMethod(name, argumentsTypes, false);
+    }
+
+    @Override
+    public List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        NodeList<Expression> resources = wrappedNode.getResources();
+        for (int i=0;i<resources.size();i++) {
+            if (child == resources.get(i)) {
+                return resources.subList(0, i).stream()
+                        .map(e -> e instanceof VariableDeclarationExpr ? ((VariableDeclarationExpr) e).getVariables()
+                                : Collections.<VariableDeclarator>emptyList())
+                        .flatMap(List::stream)
+                        .collect(Collectors.toList());
+            }
+        }
+        if (child == wrappedNode.getTryBlock()) {
+            List<VariableDeclarator> res = new LinkedList<>();
+            for (Expression expr : resources) {
+                if (expr instanceof VariableDeclarationExpr) {
+                    res.addAll(((VariableDeclarationExpr)expr).getVariables());
+                }
+            }
+            return res;
+        }
+        return Collections.emptyList();
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/VariableDeclarationExprContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/VariableDeclarationExprContext.java
new file mode 100644
index 0000000..68543f4
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/VariableDeclarationExprContext.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class VariableDeclarationExprContext extends AbstractJavaParserContext<VariableDeclarationExpr> {
+
+    public VariableDeclarationExprContext(VariableDeclarationExpr wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        for (int i=0;i<wrappedNode.getVariables().size();i++) {
+            if (child == wrappedNode.getVariable(i)) {
+                return wrappedNode.getVariables().subList(0, i);
+            }
+        }
+        return Collections.emptyList();
+    }
+
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/VariableDeclaratorContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/VariableDeclaratorContext.java
new file mode 100644
index 0000000..6cc4494
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/VariableDeclaratorContext.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class VariableDeclaratorContext extends AbstractJavaParserContext<VariableDeclarator> {
+
+    public VariableDeclaratorContext(VariableDeclarator wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public List<VariableDeclarator> localVariablesExposedToChild(Node child) {
+        if (wrappedNode.getInitializer().isPresent() && wrappedNode.getInitializer().get() == child) {
+            return Collections.singletonList(wrappedNode);
+        }
+        return Collections.emptyList();
+    }
+
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/AstResolutionUtils.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/AstResolutionUtils.java
new file mode 100644
index 0000000..74e15d3
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/AstResolutionUtils.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.expr.AnnotationExpr;
+import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
+import com.github.javaparser.ast.nodeTypes.NodeWithConstructors;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+class AstResolutionUtils {
+
+    static String containerName(Node container) {
+        String packageName = getPackageName(container);
+        String className = getClassName("", container);
+        return packageName +
+                ((!packageName.isEmpty() && !className.isEmpty()) ? "." : "") +
+                className;
+    }
+
+    static String getPackageName(Node container) {
+        if (container instanceof CompilationUnit) {
+            Optional<PackageDeclaration> p = ((CompilationUnit) container).getPackageDeclaration();
+            if (p.isPresent()) {
+                return p.get().getName().toString();
+            }
+        } else if (container != null) {
+            return getPackageName(container.getParentNode().orElse(null));
+        }
+        return "";
+    }
+
+    static String getClassName(String base, Node container) {
+        if (container instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) {
+            String b = getClassName(base, container.getParentNode().orElse(null));
+            String cn = ((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) container).getName().getId();
+            if (b.isEmpty()) {
+                return cn;
+            } else {
+                return b + "." + cn;
+            }
+        } else if (container instanceof com.github.javaparser.ast.body.EnumDeclaration) {
+            String b = getClassName(base, container.getParentNode().orElse(null));
+            String cn = ((com.github.javaparser.ast.body.EnumDeclaration) container).getName().getId();
+            if (b.isEmpty()) {
+                return cn;
+            } else {
+                return b + "." + cn;
+            }
+        } else if (container != null) {
+            return getClassName(base, container.getParentNode().orElse(null));
+        }
+        return base;
+    }
+
+    static boolean hasDirectlyAnnotation(NodeWithAnnotations<?> nodeWithAnnotations, TypeSolver typeSolver,
+                                         String canonicalName) {
+        for (AnnotationExpr annotationExpr : nodeWithAnnotations.getAnnotations()) {
+            SymbolReference<ResolvedTypeDeclaration> ref = JavaParserFactory.getContext(annotationExpr, typeSolver)
+                    .solveType(annotationExpr.getName().getId());
+            if (ref.isSolved()) {
+                if (ref.getCorrespondingDeclaration().getQualifiedName().equals(canonicalName)) {
+                    return true;
+                }
+            } else {
+                throw new UnsolvedSymbolException(annotationExpr.getName().getId());
+            }
+        }
+        return false;
+    }
+
+    static <N extends ResolvedReferenceTypeDeclaration> List<ResolvedConstructorDeclaration> getConstructors(NodeWithConstructors<?> wrappedNode,
+                                                                TypeSolver typeSolver,
+                                                                N container) {
+        List<ResolvedConstructorDeclaration> declared = wrappedNode.getConstructors().stream()
+                .map(c -> new JavaParserConstructorDeclaration<N>(container, c, typeSolver))
+                .collect(Collectors.toList());
+        if (declared.isEmpty()) {
+            // If there are no constructors insert the default constructor
+            return ImmutableList.of(new DefaultConstructorDeclaration<N>(container));
+        } else {
+            return declared;
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java
index aff7c7c..a679b59 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java
@@ -17,14 +17,14 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
 import com.github.javaparser.ast.AccessSpecifier;
-import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedType;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 
 /**
  * This represents the default constructor added by the compiler for objects not declaring one.
@@ -32,17 +32,17 @@
  *
  * @author Federico Tomassetti
  */
-class DefaultConstructorDeclaration implements ResolvedConstructorDeclaration {
+public class DefaultConstructorDeclaration<N extends ResolvedReferenceTypeDeclaration> implements ResolvedConstructorDeclaration {
 
-    private ResolvedClassDeclaration classDeclaration;
+    private N declaringType;
 
-    DefaultConstructorDeclaration(ResolvedClassDeclaration classDeclaration) {
-        this.classDeclaration = classDeclaration;
+    DefaultConstructorDeclaration(N declaringType) {
+        this.declaringType = declaringType;
     }
 
     @Override
-    public ResolvedClassDeclaration declaringType() {
-        return classDeclaration;
+    public N declaringType() {
+        return declaringType;
     }
 
     @Override
@@ -52,12 +52,12 @@
 
     @Override
     public ResolvedParameterDeclaration getParam(int i) {
-        throw new UnsupportedOperationException("The default constructor has not parameters");
+        throw new UnsupportedOperationException("The default constructor has no parameters");
     }
 
     @Override
     public String getName() {
-        return classDeclaration.getName();
+        return declaringType.getName();
     }
 
     @Override
@@ -79,4 +79,9 @@
     public ResolvedType getSpecifiedException(int index) {
         throw new UnsupportedOperationException("The default constructor does not throw exceptions");
     }
+
+    @Override
+    public Optional<ConstructorDeclaration> toAst() {
+        return Optional.empty();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java
deleted file mode 100644
index d34e164..0000000
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
-
-import com.github.javaparser.ast.*;
-
-import java.util.EnumSet;
-import java.util.Optional;
-
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
-
-/**
- * @author Federico Tomassetti
- */
-class Helper {
-
-    public static AccessSpecifier toAccessLevel(EnumSet<Modifier> modifiers) {
-        if (modifiers.contains(Modifier.PRIVATE)) {
-            return AccessSpecifier.PRIVATE;
-        } else if (modifiers.contains(Modifier.PROTECTED)) {
-            return AccessSpecifier.PROTECTED;
-        } else if (modifiers.contains(Modifier.PUBLIC)) {
-            return AccessSpecifier.PUBLIC;
-        } else {
-            return AccessSpecifier.DEFAULT;
-        }
-    }
-
-    static String containerName(Node container) {
-        String packageName = getPackageName(container);
-        String className = getClassName("", container);
-        return packageName +
-                ((!packageName.isEmpty() && !className.isEmpty()) ? "." : "") +
-                className;
-    }
-
-    static String getPackageName(Node container) {
-        if (container instanceof CompilationUnit) {
-            Optional<PackageDeclaration> p = ((CompilationUnit) container).getPackageDeclaration();
-            if (p.isPresent()) {
-                return p.get().getName().toString();
-            }
-        } else if (container != null) {
-            return getPackageName(container.getParentNode().orElse(null));
-        }
-        return "";
-    }
-
-    static String getClassName(String base, Node container) {
-        if (container instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) {
-            String b = getClassName(base, container.getParentNode().orElse(null));
-            String cn = ((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) container).getName().getId();
-            if (b.isEmpty()) {
-                return cn;
-            } else {
-                return b + "." + cn;
-            }
-        } else if (container instanceof com.github.javaparser.ast.body.EnumDeclaration) {
-            String b = getClassName(base, container.getParentNode().orElse(null));
-            String cn = ((com.github.javaparser.ast.body.EnumDeclaration) container).getName().getId();
-            if (b.isEmpty()) {
-                return cn;
-            } else {
-                return b + "." + cn;
-            }
-        } else if (container != null) {
-            return getClassName(base, container.getParentNode().orElse(null));
-        }
-        return base;
-    }
-}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java
index 1f6c6f3..b2b0882 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java
@@ -8,13 +8,12 @@
 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
-
 /**
  * @author Federico Tomassetti
  */
@@ -29,22 +28,25 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         throw new UnsupportedOperationException();
     }
 
     @Override
     public List<ResolvedFieldDeclaration> getAllFields() {
+        // TODO #1837
         throw new UnsupportedOperationException();
     }
 
     @Override
     public Set<ResolvedMethodDeclaration> getDeclaredMethods() {
+        // TODO #1838
         throw new UnsupportedOperationException();
     }
 
     @Override
     public boolean isAssignableBy(ResolvedType type) {
+        // TODO #1836
         throw new UnsupportedOperationException();
     }
 
@@ -54,23 +56,23 @@
     }
 
     @Override
-    public boolean hasDirectlyAnnotation(String qualifiedName) {
-        throw new UnsupportedOperationException();
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        return AstResolutionUtils.hasDirectlyAnnotation(wrappedNode, typeSolver, canonicalName);
     }
 
     @Override
     public String getPackageName() {
-        return Helper.getPackageName(wrappedNode);
+        return AstResolutionUtils.getPackageName(wrappedNode);
     }
 
     @Override
     public String getClassName() {
-        return Helper.getClassName("", wrappedNode);
+        return AstResolutionUtils.getClassName("", wrappedNode);
     }
 
     @Override
     public String getQualifiedName() {
-        String containerName = Helper.containerName(wrappedNode.getParentNode().orElse(null));
+        String containerName = AstResolutionUtils.containerName(wrappedNode.getParentNode().orElse(null));
         if (containerName.isEmpty()) {
             return wrappedNode.getName().getId();
         } else {
@@ -83,13 +85,20 @@
         return wrappedNode.getName().getId();
     }
 
+    /**
+     * Annotation declarations cannot have type parameters and hence this method always returns an empty list.
+     *
+     * @return An empty list.
+     */
     @Override
     public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
-        throw new UnsupportedOperationException();
+        // Annotation declarations cannot have type parameters - i.e. we can always return an empty list.
+        return Collections.emptyList();
     }
 
     @Override
     public Optional<ResolvedReferenceTypeDeclaration> containerType() {
+        // TODO #1841
         throw new UnsupportedOperationException("containerType is not supported for " + this.getClass().getCanonicalName());
     }
 
@@ -100,4 +109,14 @@
                 .map(m -> new JavaParserAnnotationMemberDeclaration((AnnotationMemberDeclaration)m, typeSolver))
                 .collect(Collectors.toList());
     }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Optional<AnnotationDeclaration> toAst() {
+        return Optional.of(wrappedNode);
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java
index 3d2cb8f..19d4bf2 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java
@@ -1,17 +1,19 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
-
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
 import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.google.common.collect.ImmutableList;
@@ -23,7 +25,8 @@
 /**
  * An anonymous class declaration representation.
  */
-public class JavaParserAnonymousClassDeclaration extends AbstractClassDeclaration {
+public class JavaParserAnonymousClassDeclaration extends AbstractClassDeclaration
+        implements MethodUsageResolutionCapability {
 
   private final TypeSolver typeSolver;
   private final ObjectCreationExpr wrappedNode;
@@ -34,9 +37,16 @@
                                              TypeSolver typeSolver) {
     this.typeSolver = typeSolver;
     this.wrappedNode = wrappedNode;
+
+    ClassOrInterfaceType superType = wrappedNode.getType();
+    String superTypeName = superType.getName().getId();
+    if (superType.getScope().isPresent()) {
+      superTypeName = superType.getScope().get().asString() + "." + superTypeName;
+    }
+
     superTypeDeclaration =
         JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver)
-                         .solveType(wrappedNode.getType().getName().getId(), typeSolver)
+                         .solveType(superTypeName)
                          .getCorrespondingDeclaration();
   }
 
@@ -63,13 +73,29 @@
   }
 
   @Override
+  public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
+                                                                boolean staticOnly) {
+    return getContext().solveMethod(name, argumentsTypes, staticOnly);
+  }
+
+  @Override
+  public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentTypes,
+                                                  Context invocationContext, List<ResolvedType> typeParameters) {
+    return getContext().solveMethodAsUsage(name, argumentTypes);
+  }
+
+  @Override
   protected ResolvedReferenceType object() {
     return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
   }
 
   @Override
   public ResolvedReferenceType getSuperClass() {
-    return new ReferenceTypeImpl(superTypeDeclaration.asReferenceType(), typeSolver);
+    ResolvedReferenceTypeDeclaration superRRTD = superTypeDeclaration.asReferenceType();
+    if (superRRTD == null) {
+      throw new RuntimeException("The super ResolvedReferenceTypeDeclaration is not expected to be null");
+    }
+    return new ReferenceTypeImpl(superRRTD, typeSolver);
   }
 
   @Override
@@ -87,7 +113,7 @@
     return
         findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class)
             .stream()
-            .map(ctor -> new JavaParserConstructorDeclaration(this, ctor, typeSolver))
+            .map(ctor -> new JavaParserConstructorDeclaration<>(this, ctor, typeSolver))
             .collect(Collectors.toList());
   }
 
@@ -97,12 +123,12 @@
   }
 
   @Override
-  public List<ResolvedReferenceType> getAncestors() {
+  public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
     return
         ImmutableList.
             <ResolvedReferenceType>builder()
             .add(getSuperClass())
-            .addAll(superTypeDeclaration.asReferenceType().getAncestors())
+            .addAll(superTypeDeclaration.asReferenceType().getAncestors(acceptIncompleteList))
             .build();
   }
 
@@ -161,17 +187,17 @@
 
   @Override
   public String getPackageName() {
-    return Helper.getPackageName(wrappedNode);
+    return AstResolutionUtils.getPackageName(wrappedNode);
   }
 
   @Override
   public String getClassName() {
-    return Helper.getClassName("", wrappedNode);
+    return AstResolutionUtils.getClassName("", wrappedNode);
   }
 
   @Override
   public String getQualifiedName() {
-    String containerName = Helper.containerName(wrappedNode.getParentNode().orElse(null));
+    String containerName = AstResolutionUtils.containerName(wrappedNode.getParentNode().orElse(null));
     if (containerName.isEmpty()) {
       return getName();
     } else {
@@ -202,4 +228,10 @@
   public Optional<ResolvedReferenceTypeDeclaration> containerType() {
     throw new UnsupportedOperationException("containerType is not supported for " + this.getClass().getCanonicalName());
   }
+
+  @Override
+  public Optional<Node> toAst() {
+    return Optional.of(wrappedNode);
+  }
+
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java
index bb9f91c..0471fad 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java
@@ -17,15 +17,17 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
 import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
@@ -34,7 +36,6 @@
 import com.github.javaparser.symbolsolver.model.typesystem.LazyType;
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
-import com.google.common.collect.ImmutableList;
 
 import java.util.*;
 import java.util.stream.Collectors;
@@ -42,7 +43,7 @@
 /**
  * @author Federico Tomassetti
  */
-public class JavaParserClassDeclaration extends AbstractClassDeclaration {
+public class JavaParserClassDeclaration extends AbstractClassDeclaration implements MethodUsageResolutionCapability {
 
     ///
     /// Fields
@@ -90,8 +91,8 @@
     @Override
     public String toString() {
         return "JavaParserClassDeclaration{" +
-                "wrappedNode=" + wrappedNode +
-                '}';
+               "wrappedNode=" + wrappedNode +
+               '}';
     }
 
     ///
@@ -101,49 +102,59 @@
     @Override
     public List<ResolvedFieldDeclaration> getAllFields() {
         List<ResolvedFieldDeclaration> fields = javaParserTypeAdapter.getFieldsForDeclaredVariables();
-        
-        getAncestors().forEach(ancestor -> ancestor.getTypeDeclaration().getAllFields().forEach(f -> {
+
+        getAncestors(true).forEach(ancestor -> ancestor.getTypeDeclaration().getAllFields().forEach(f -> {
             fields.add(new ResolvedFieldDeclaration() {
-                
+
                 @Override
                 public AccessSpecifier accessSpecifier() {
                     return f.accessSpecifier();
                 }
-                
+
                 @Override
                 public String getName() {
                     return f.getName();
                 }
-                
+
                 @Override
                 public ResolvedType getType() {
                     return ancestor.useThisTypeParametersOnTheGivenType(f.getType());
                 }
-                
+
                 @Override
                 public boolean isStatic() {
                     return f.isStatic();
                 }
-                
+
                 @Override
                 public ResolvedTypeDeclaration declaringType() {
                     return f.declaringType();
                 }
             });
         }));
-        
+
         return fields;
     }
-    
+
     ///
     /// Public methods
     ///
 
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes) {
         Context ctx = getContext();
-        return ctx.solveMethod(name, parameterTypes, false, typeSolver);
+        return ctx.solveMethod(name, parameterTypes, false);
     }
 
+    @Override
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentTypes,
+                                                    Context invocationContext, List<ResolvedType> typeParameters) {
+        return getContext().solveMethodAsUsage(name, argumentTypes);
+    }
+
+    /**
+     * This method is deprecated because the context is an implementation detail that should not be exposed.
+     * Ideally this method should become private. For this reason all further usages of this method are discouraged.
+     */
     @Deprecated
     public Context getContext() {
         return JavaParserFactory.getContext(wrappedNode, typeSolver);
@@ -180,29 +191,12 @@
 
     @Override
     public List<ResolvedConstructorDeclaration> getConstructors() {
-        List<ResolvedConstructorDeclaration> declared = new LinkedList<>();
-        for (BodyDeclaration<?> member : wrappedNode.getMembers()) {
-            if (member instanceof com.github.javaparser.ast.body.ConstructorDeclaration) {
-                com.github.javaparser.ast.body.ConstructorDeclaration constructorDeclaration = (com.github.javaparser.ast.body.ConstructorDeclaration) member;
-                declared.add(new JavaParserConstructorDeclaration(this, constructorDeclaration, typeSolver));
-            }
-        }
-        if (declared.isEmpty()) {
-            // If there are no constructors insert the default constructor
-            return ImmutableList.of(new DefaultConstructorDeclaration(this));
-        } else {
-            return declared;
-        }
+        return AstResolutionUtils.getConstructors(this.wrappedNode, typeSolver, this);
     }
 
     @Override
     public boolean hasDirectlyAnnotation(String canonicalName) {
-        for (AnnotationExpr annotationExpr : wrappedNode.getAnnotations()) {
-            if (solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName)) {
-                return true;
-            }
-        }
-        return false;
+        return AstResolutionUtils.hasDirectlyAnnotation(wrappedNode, typeSolver, canonicalName);
     }
 
     @Override
@@ -269,38 +263,74 @@
         return false;
     }
 
+    /**
+     * Resolution should move out of declarations, so that they are pure declarations and the resolution should
+     * work for JavaParser, Reflection and Javassist classes in the same way and not be specific to the three
+     * implementations.
+     */
     @Deprecated
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
         if (this.wrappedNode.getName().getId().equals(name)) {
             return SymbolReference.solved(this);
         }
-        SymbolReference<ResolvedTypeDeclaration> ref = javaParserTypeAdapter.solveType(name, typeSolver);
+        SymbolReference<ResolvedTypeDeclaration> ref = javaParserTypeAdapter.solveType(name);
         if (ref.isSolved()) {
             return ref;
         }
 
         String prefix = wrappedNode.getName() + ".";
         if (name.startsWith(prefix) && name.length() > prefix.length()) {
-            return new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
+            return new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()));
         }
 
-        return getContext().getParent().solveType(name, typeSolver);
+        return getContext().getParent().solveType(name);
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
+                                                                  boolean staticOnly) {
+        return getContext().solveMethod(name, argumentsTypes, staticOnly);
+    }
+
+    @Override
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         List<ResolvedReferenceType> ancestors = new ArrayList<>();
 
         // We want to avoid infinite recursion in case of Object having Object as ancestor
         if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) {
-            ResolvedReferenceType superclass = getSuperClass();
+            ResolvedReferenceType superclass;
+            try {
+                superclass = getSuperClass();
+            } catch (UnsolvedSymbolException e) {
+                if (acceptIncompleteList) {
+                    // in case we could not resolve the super class, we may still be able to resolve (some of) the
+                    // implemented interfaces and so we continue gracefully with an (incomplete) list of ancestors
+                    superclass = null;
+                } else {
+                    throw e;
+                }
+            }
             if (superclass != null) {
                 ancestors.add(superclass);
             }
             if (wrappedNode.getImplementedTypes() != null) {
                 for (ClassOrInterfaceType implemented : wrappedNode.getImplementedTypes()) {
-                    ResolvedReferenceType ancestor = toReferenceType(implemented);
-                    ancestors.add(ancestor);
+                    ResolvedReferenceType ancestor;
+                    try {
+                        ancestor = toReferenceType(implemented);
+                    } catch (UnsolvedSymbolException e) {
+                        if (acceptIncompleteList) {
+                            // in case we could not resolve some implemented interface, we may still be able to resolve the
+                            // extended class or (some of) the other implemented interfaces and so we continue gracefully
+                            // with an (incomplete) list of ancestors
+                            ancestor = null;
+                        } else {
+                            throw e;
+                        }
+                    }
+                    if (ancestor != null) {
+                        ancestors.add(ancestor);
+                    }
                 }
             }
         }
@@ -337,7 +367,12 @@
 
     @Override
     public AccessSpecifier accessSpecifier() {
-        return Helper.toAccessLevel(wrappedNode.getModifiers());
+        return wrappedNode.getAccessSpecifier();
+    }
+
+    @Override
+    public Optional<Node> toAst() {
+        return Optional.of(wrappedNode);
     }
 
     ///
@@ -354,7 +389,7 @@
         Set<ResolvedReferenceTypeDeclaration> res = new HashSet<>();
         for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) {
             if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
-                res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member));
+                res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member));
             }
         }
         return res;
@@ -375,12 +410,12 @@
             // look for the qualified name (for example class of type Rectangle2D.Double)
             className = classOrInterfaceType.getScope().get().toString() + "." + className;
         }
-        SymbolReference<ResolvedTypeDeclaration> ref = solveType(className, typeSolver);
+        SymbolReference<ResolvedTypeDeclaration> ref = solveType(className);
         if (!ref.isSolved()) {
             Optional<ClassOrInterfaceType> localScope = classOrInterfaceType.getScope();
             if (localScope.isPresent()) {
                 String localName = localScope.get().getName().getId() + "." + classOrInterfaceType.getName().getId();
-                ref = solveType(localName, typeSolver);
+                ref = solveType(localName);
             }
         }
         if (!ref.isSolved()) {
@@ -390,8 +425,8 @@
             return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), typeSolver);
         }
         List<ResolvedType> superClassTypeParameters = classOrInterfaceType.getTypeArguments().get()
-                .stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta)))
-                .collect(Collectors.toList());
+                                                              .stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta)))
+                                                              .collect(Collectors.toList());
         return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), superClassTypeParameters, typeSolver);
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java
index e9500fe..cf823b2 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java
@@ -17,36 +17,36 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
 import com.github.javaparser.ast.AccessSpecifier;
-import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
  * @author Federico Tomassetti
  */
-public class JavaParserConstructorDeclaration implements ResolvedConstructorDeclaration {
+public class JavaParserConstructorDeclaration<N extends ResolvedReferenceTypeDeclaration> implements ResolvedConstructorDeclaration {
 
-    private ResolvedClassDeclaration classDeclaration;
+    private N declaringType;
     private com.github.javaparser.ast.body.ConstructorDeclaration wrappedNode;
     private TypeSolver typeSolver;
 
-    JavaParserConstructorDeclaration(ResolvedClassDeclaration classDeclaration, com.github.javaparser.ast.body.ConstructorDeclaration wrappedNode,
+    JavaParserConstructorDeclaration(N declaringType, com.github.javaparser.ast.body.ConstructorDeclaration wrappedNode,
                                      TypeSolver typeSolver) {
-        this.classDeclaration = classDeclaration;
+        this.declaringType = declaringType;
         this.wrappedNode = wrappedNode;
         this.typeSolver = typeSolver;
     }
 
     @Override
-    public ResolvedClassDeclaration declaringType() {
-        return classDeclaration;
+    public N declaringType() {
+        return declaringType;
     }
 
     @Override
@@ -64,7 +64,7 @@
 
     @Override
     public String getName() {
-        return this.classDeclaration.getName();
+        return this.declaringType.getName();
     }
 
     /**
@@ -78,7 +78,7 @@
     
     @Override
     public AccessSpecifier accessSpecifier() {
-        return Helper.toAccessLevel(wrappedNode.getModifiers());
+        return wrappedNode.getAccessSpecifier();
     }
 
     @Override
@@ -100,4 +100,9 @@
         return JavaParserFacade.get(typeSolver)
                 .convert(wrappedNode.getThrownExceptions().get(index), wrappedNode);
     }
+
+    @Override
+    public Optional<ConstructorDeclaration> toAst() {
+        return Optional.of(wrappedNode);
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java
index 818c060..85742ca 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java
@@ -19,7 +19,8 @@
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.BodyDeclaration;
-import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
@@ -29,14 +30,17 @@
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
+import com.github.javaparser.symbolsolver.core.resolution.TypeVariableResolutionCapability;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.logic.MethodResolutionCapability;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.LazyType;
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
-import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
 
 import java.io.Serializable;
 import java.util.*;
@@ -45,7 +49,8 @@
 /**
  * @author Federico Tomassetti
  */
-public class JavaParserEnumDeclaration extends AbstractTypeDeclaration implements ResolvedEnumDeclaration {
+public class JavaParserEnumDeclaration extends AbstractTypeDeclaration
+        implements ResolvedEnumDeclaration, MethodResolutionCapability, MethodUsageResolutionCapability {
 
     private TypeSolver typeSolver;
     private com.github.javaparser.ast.body.EnumDeclaration wrappedNode;
@@ -101,7 +106,7 @@
 
     @Override
     public boolean hasDirectlyAnnotation(String canonicalName) {
-        throw new UnsupportedOperationException();
+        return AstResolutionUtils.hasDirectlyAnnotation(wrappedNode, typeSolver, canonicalName);
     }
 
     @Override
@@ -184,31 +189,37 @@
         return wrappedNode.hashCode();
     }
 
-    @Deprecated
-    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> parameterTypes,
-                                                    TypeSolver typeSolver, Context invokationContext, List<ResolvedType> typeParameterValues) {
-        if (name.equals("values") && parameterTypes.isEmpty()) {
-            return Optional.of(new ValuesMethod(this, typeSolver).getUsage(null));
+    @Override
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentTypes,
+                                                    Context invokationContext, List<ResolvedType> typeParameters) {
+        return getContext().solveMethodAsUsage(name, argumentTypes);
+    }
+
+    @Override
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
+                                                                  boolean staticOnly) {
+        if (name.equals("values") && argumentsTypes.isEmpty()) {
+            return SymbolReference.solved(new JavaParserEnumDeclaration.ValuesMethod(this, typeSolver));
         }
-        // TODO add methods inherited from Enum
-        return getContext().solveMethodAsUsage(name, parameterTypes, typeSolver);
+        return getContext().solveMethod(name, argumentsTypes, staticOnly);
     }
 
     @Override
     public List<ResolvedFieldDeclaration> getAllFields() {
         List<ResolvedFieldDeclaration> fields = javaParserTypeAdapter.getFieldsForDeclaredVariables();
 
-        if (this.wrappedNode.getEntries() != null) {
-            for (EnumConstantDeclaration member : this.wrappedNode.getEntries()) {
-                fields.add(new JavaParserFieldDeclaration(member, typeSolver));
-            }
-        }
+        this.getAncestors().forEach(a -> fields.addAll(a.getAllFieldsVisibleToInheritors()));
+
+        this.wrappedNode.getMembers().stream().filter(m -> m instanceof FieldDeclaration).forEach(m -> {
+                FieldDeclaration fd = (FieldDeclaration)m;
+                fd.getVariables().forEach(v -> fields.add(new JavaParserFieldDeclaration(v, typeSolver)));
+        });
 
         return fields;
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         List<ResolvedReferenceType> ancestors = new ArrayList<>();
         ResolvedReferenceType enumClass = ReflectionFactory.typeUsageFor(Enum.class, typeSolver).asReferenceType();
         ResolvedTypeParameterDeclaration eTypeParameter = enumClass.getTypeDeclaration().getTypeParameters().get(0);
@@ -216,16 +227,58 @@
         ancestors.add(enumClass);
         if (wrappedNode.getImplementedTypes() != null) {
             for (ClassOrInterfaceType implementedType : wrappedNode.getImplementedTypes()) {
-                SymbolReference<ResolvedTypeDeclaration> implementedDeclRef = new SymbolSolver(typeSolver).solveTypeInType(this, implementedType.getName().getId());
-                if (!implementedDeclRef.isSolved()) {
-                    throw new UnsolvedSymbolException(implementedType.getName().getId());
+                try {
+                    ancestors.add(toReferenceType(implementedType));
+                } catch (UnsolvedSymbolException e) {
+                    if (!acceptIncompleteList) {
+                        throw e;
+                    }
                 }
-                ancestors.add(new ReferenceTypeImpl((ResolvedReferenceTypeDeclaration) implementedDeclRef.getCorrespondingDeclaration(), typeSolver));
             }
         }
         return ancestors;
     }
 
+    private ResolvedReferenceType toReferenceType(ClassOrInterfaceType classOrInterfaceType) {
+        String className = classOrInterfaceType.getName().getId();
+        if (classOrInterfaceType.getScope().isPresent()) {
+            // look for the qualified name (for example class of type Rectangle2D.Double)
+            className = classOrInterfaceType.getScope().get().toString() + "." + className;
+        }
+        SymbolReference<ResolvedTypeDeclaration> ref = solveType(className);
+        if (!ref.isSolved()) {
+            throw new UnsolvedSymbolException(classOrInterfaceType.getName().getId());
+        }
+        if (!classOrInterfaceType.getTypeArguments().isPresent()) {
+            return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), typeSolver);
+        }
+        List<ResolvedType> superClassTypeParameters = classOrInterfaceType.getTypeArguments().get()
+                .stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta)))
+                .collect(Collectors.toList());
+        return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), superClassTypeParameters, typeSolver);
+    }
+
+    /**
+     * This method is deprecated because it receives the TypesSolver as a parameter.
+     * Eventually we would like to remove all usages of TypeSolver as a parameter.
+     *
+     * Also, resolution should move out of declarations, so that they are pure declarations and the resolution should
+     * work for JavaParser, Reflection and Javassist classes in the same way and not be specific to the three
+     * implementations.
+     */
+    @Deprecated
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
+        if (this.wrappedNode.getName().getId().equals(name)) {
+            return SymbolReference.solved(this);
+        }
+        SymbolReference<ResolvedTypeDeclaration> ref = javaParserTypeAdapter.solveType(name);
+        if (ref.isSolved()) {
+            return ref;
+        }
+
+        return getContext().getParent().solveType(name);
+    }
+
     @Override
     public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
         return Collections.emptyList();
@@ -248,7 +301,7 @@
     }
 
     // Needed by ContextHelper
-    public static class ValuesMethod implements ResolvedMethodDeclaration {
+    public static class ValuesMethod implements ResolvedMethodDeclaration, TypeVariableResolutionCapability {
 
         private JavaParserEnumDeclaration enumDeclaration;
         private TypeSolver typeSolver;
@@ -313,7 +366,7 @@
 
         @Override
         public AccessSpecifier accessSpecifier() {
-            return Helper.toAccessLevel(enumDeclaration.getWrappedNode().getModifiers());
+            return enumDeclaration.getWrappedNode().getAccessSpecifier();
         }
 
         @Override
@@ -325,6 +378,11 @@
         public ResolvedType getSpecifiedException(int index) {
             throw new UnsupportedOperationException("The values method of an enum does not throw any exception");
         }
+
+        @Override
+        public Optional<MethodDeclaration> toAst() {
+            return Optional.empty();
+        }
     }
 
     @Override
@@ -347,4 +405,9 @@
     public Optional<ResolvedReferenceTypeDeclaration> containerType() {
         return javaParserTypeAdapter.containerType();
     }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return AstResolutionUtils.getConstructors(this.wrappedNode, typeSolver, this);
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java
index 1c9e005..9d4cc8c 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java
@@ -19,18 +19,16 @@
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.ast.body.TypeDeclaration;
 import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 
 import java.util.Optional;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
 
 /**
@@ -40,7 +38,6 @@
 
     private VariableDeclarator variableDeclarator;
     private com.github.javaparser.ast.body.FieldDeclaration wrappedNode;
-    private EnumConstantDeclaration enumConstantDeclaration;
     private TypeSolver typeSolver;
 
     public JavaParserFieldDeclaration(VariableDeclarator variableDeclarator, TypeSolver typeSolver) {
@@ -55,35 +52,19 @@
         this.wrappedNode = (com.github.javaparser.ast.body.FieldDeclaration) requireParentNode(variableDeclarator);
     }
 
-    public JavaParserFieldDeclaration(EnumConstantDeclaration enumConstantDeclaration, TypeSolver typeSolver) {
-        if (typeSolver == null) {
-            throw new IllegalArgumentException("typeSolver should not be null");
-        }
-        this.enumConstantDeclaration = enumConstantDeclaration;
-        this.typeSolver = typeSolver;
-    }
-
     @Override
     public ResolvedType getType() {
-        if (enumConstantDeclaration != null) {
-            com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = (com.github.javaparser.ast.body.EnumDeclaration) requireParentNode(enumConstantDeclaration);
-            return new ReferenceTypeImpl(new JavaParserEnumDeclaration(enumDeclaration, typeSolver), typeSolver);
-        }
         return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), wrappedNode);
     }
 
     @Override
     public String getName() {
-        if (enumConstantDeclaration != null) {
-            return enumConstantDeclaration.getName().getId();
-        } else {
-            return variableDeclarator.getName().getId();
-        }
+        return variableDeclarator.getName().getId();
     }
 
     @Override
     public boolean isStatic() {
-        return wrappedNode.getModifiers().contains(Modifier.STATIC);
+        return wrappedNode.hasModifier(Modifier.Keyword.STATIC);
     }
 
     @Override
@@ -100,19 +81,23 @@
         return wrappedNode;
     }
 
+    public VariableDeclarator getVariableDeclarator() {
+        return variableDeclarator;
+    }
+
     @Override
     public String toString() {
-        return "JPField{" + getName() + "}";
+        return "JavaParserFieldDeclaration{" + getName() + "}";
     }
 
     @Override
     public AccessSpecifier accessSpecifier() {
-        return Helper.toAccessLevel(wrappedNode.getModifiers());
+        return wrappedNode.getAccessSpecifier();
     }
 
     @Override
     public ResolvedTypeDeclaration declaringType() {
-        Optional<com.github.javaparser.ast.body.TypeDeclaration> typeDeclaration = wrappedNode.findParent(com.github.javaparser.ast.body.TypeDeclaration.class);
+        Optional<TypeDeclaration> typeDeclaration = wrappedNode.findAncestor(TypeDeclaration.class);
         if (typeDeclaration.isPresent()) {
             return JavaParserFacade.get(typeSolver).getTypeDeclaration(typeDeclaration.get());
         }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java
index 34955a0..f29adda 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java
@@ -20,16 +20,18 @@
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.BodyDeclaration;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.expr.AnnotationExpr;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.logic.MethodResolutionCapability;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.LazyType;
@@ -42,7 +44,8 @@
 /**
  * @author Federico Tomassetti
  */
-public class JavaParserInterfaceDeclaration extends AbstractTypeDeclaration implements ResolvedInterfaceDeclaration {
+public class JavaParserInterfaceDeclaration extends AbstractTypeDeclaration
+        implements ResolvedInterfaceDeclaration, MethodResolutionCapability, MethodUsageResolutionCapability {
 
     private TypeSolver typeSolver;
     private ClassOrInterfaceDeclaration wrappedNode;
@@ -105,12 +108,7 @@
 
     @Override
     public boolean hasDirectlyAnnotation(String canonicalName) {
-        for (AnnotationExpr annotationExpr : wrappedNode.getAnnotations()) {
-            if (solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName)) {
-                return true;
-            }
-        }
-        return false;
+        return AstResolutionUtils.hasDirectlyAnnotation(wrappedNode, typeSolver, canonicalName);
     }
 
     @Override
@@ -121,10 +119,9 @@
     @Override
     public List<ResolvedReferenceType> getInterfacesExtended() {
         List<ResolvedReferenceType> interfaces = new ArrayList<>();
-        if (wrappedNode.getImplementedTypes() != null) {
-            for (ClassOrInterfaceType t : wrappedNode.getImplementedTypes()) {
-                interfaces.add(new ReferenceTypeImpl(solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration().asInterface(), typeSolver));
-            }
+        for (ClassOrInterfaceType t : wrappedNode.getExtendedTypes()) {
+            interfaces.add(new ReferenceTypeImpl(
+                    solveType(t.getName().getId()).getCorrespondingDeclaration().asInterface(), typeSolver));
         }
         return interfaces;
     }
@@ -231,35 +228,69 @@
                 '}';
     }
 
+    /**
+     * This method is deprecated because it receives the TypesSolver as a parameter.
+     * Eventually we would like to remove all usages of TypeSolver as a parameter.
+     *
+     * Also, resolution should move out of declarations, so that they are pure declarations and the resolution should
+     * work for JavaParser, Reflection and Javassist classes in the same way and not be specific to the three
+     * implementations.
+     */
     @Deprecated
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
         if (this.wrappedNode.getName().getId().equals(name)) {
             return SymbolReference.solved(this);
         }
-        SymbolReference<ResolvedTypeDeclaration> ref = javaParserTypeAdapter.solveType(name, typeSolver);
+        SymbolReference<ResolvedTypeDeclaration> ref = javaParserTypeAdapter.solveType(name);
         if (ref.isSolved()) {
             return ref;
         }
 
         String prefix = wrappedNode.getName() + ".";
         if (name.startsWith(prefix) && name.length() > prefix.length()) {
-            return new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
+            return new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()));
         }
 
-        return getContext().getParent().solveType(name, typeSolver);
+        return getContext().getParent().solveType(name);
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
+                                                                  boolean staticOnly) {
+        return getContext().solveMethod(name, argumentsTypes, staticOnly);
+    }
+
+    @Override
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentTypes,
+                                                    Context invocationContext, List<ResolvedType> typeParameters) {
+        return getContext().solveMethodAsUsage(name, argumentTypes);
+    }
+
+    @Override
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         List<ResolvedReferenceType> ancestors = new ArrayList<>();
         if (wrappedNode.getExtendedTypes() != null) {
             for (ClassOrInterfaceType extended : wrappedNode.getExtendedTypes()) {
-                ancestors.add(toReferenceType(extended));
+                try {
+                    ancestors.add(toReferenceType(extended));
+                } catch (UnsolvedSymbolException e) {
+                    if (!acceptIncompleteList) {
+                        // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully
+                        throw e;
+                    }
+                }
             }
         }
         if (wrappedNode.getImplementedTypes() != null) {
             for (ClassOrInterfaceType implemented : wrappedNode.getImplementedTypes()) {
-                ancestors.add(toReferenceType(implemented));
+                try {
+                    ancestors.add(toReferenceType(implemented));
+                } catch (UnsolvedSymbolException e) {
+                    if (!acceptIncompleteList) {
+                        // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully
+                        throw e;
+                    }
+                }
             }
         }
         return ancestors;
@@ -287,7 +318,7 @@
 
     @Override
     public AccessSpecifier accessSpecifier() {
-        return Helper.toAccessLevel(wrappedNode.getModifiers());
+        return wrappedNode.getAccessSpecifier();
     }
 
     @Override
@@ -306,20 +337,32 @@
         return javaParserTypeAdapter.containerType();
     }
 
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Optional<ClassOrInterfaceDeclaration> toAst() {
+        return Optional.of(wrappedNode);
+    }
+
     ///
     /// Private methods
     ///
 
     private ResolvedReferenceType toReferenceType(ClassOrInterfaceType classOrInterfaceType) {
         SymbolReference<? extends ResolvedTypeDeclaration> ref = null;
-        if (classOrInterfaceType.toString().indexOf('.') > -1) {
-            ref = typeSolver.tryToSolveType(classOrInterfaceType.toString());
+        String typeName = classOrInterfaceType.getName().getId();
+        if (classOrInterfaceType.getScope().isPresent()) {
+            typeName = classOrInterfaceType.getScope().get().asString() + "." + typeName;
+        }
+
+        if (typeName.indexOf('.') > -1) {
+            ref = typeSolver.tryToSolveType(typeName);
         }
         if (ref == null || !ref.isSolved()) {
-            ref = solveType(classOrInterfaceType.toString(), typeSolver);
-        }
-        if (!ref.isSolved()) {
-            ref = solveType(classOrInterfaceType.getName().getId(), typeSolver);
+            ref = solveType(typeName);
         }
         if (!ref.isSolved()) {
             throw new UnsolvedSymbolException(classOrInterfaceType.getName().getId());
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java
index 4f3cb35..96b1920 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java
@@ -17,7 +17,9 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.ObjectCreationExpr;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
@@ -26,12 +28,14 @@
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.TypeVariableResolutionCapability;
 import com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
@@ -39,7 +43,7 @@
 /**
  * @author Federico Tomassetti
  */
-public class JavaParserMethodDeclaration implements ResolvedMethodDeclaration {
+public class JavaParserMethodDeclaration implements ResolvedMethodDeclaration, TypeVariableResolutionCapability {
 
     private com.github.javaparser.ast.body.MethodDeclaration wrappedNode;
     private TypeSolver typeSolver;
@@ -147,7 +151,7 @@
 
     @Override
     public AccessSpecifier accessSpecifier() {
-        return Helper.toAccessLevel(wrappedNode.getModifiers());
+        return wrappedNode.getAccessSpecifier();
     }
 
     @Override
@@ -164,4 +168,9 @@
         return JavaParserFacade.get(typeSolver).convert(wrappedNode.getThrownExceptions()
                 .get(index), wrappedNode);
     }
+
+    @Override
+    public Optional<MethodDeclaration> toAst() {
+        return Optional.of(wrappedNode);
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java
index cba7d32..d3fea70 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java
@@ -70,7 +70,7 @@
     @Override
     public ResolvedType getType() {
         if (wrappedNode.getType() instanceof UnknownType && JavaParserFactory.getContext(wrappedNode, typeSolver) instanceof LambdaExprContext) {
-            Optional<Value> value = JavaParserFactory.getContext(wrappedNode, typeSolver).solveSymbolAsValue(wrappedNode.getNameAsString(), typeSolver);
+            Optional<Value> value = JavaParserFactory.getContext(wrappedNode, typeSolver).solveSymbolAsValue(wrappedNode.getNameAsString());
             if (value.isPresent()) {
                 return value.get().getType();
             }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java
index f1f1ffb..5184f19 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java
@@ -35,23 +35,21 @@
 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
 
 /**
+ * This should not be used to represent fields of parameters.
+ *
+ * Eventually this should be renamed in JavaParserVariableDeclaration.
+ *
  * @author Federico Tomassetti
  */
 public class JavaParserSymbolDeclaration implements ResolvedValueDeclaration {
 
     private String name;
     private Node wrappedNode;
-    private boolean field;
-    private boolean parameter;
-    private boolean variable;
     private TypeSolver typeSolver;
 
-    private JavaParserSymbolDeclaration(Node wrappedNode, String name, TypeSolver typeSolver, boolean field, boolean parameter, boolean variable) {
+    private JavaParserSymbolDeclaration(Node wrappedNode, String name, TypeSolver typeSolver) {
         this.name = name;
         this.wrappedNode = wrappedNode;
-        this.field = field;
-        this.variable = variable;
-        this.parameter = parameter;
         this.typeSolver = typeSolver;
     }
 
@@ -64,7 +62,7 @@
     }
 
     public static JavaParserSymbolDeclaration localVar(VariableDeclarator variableDeclarator, TypeSolver typeSolver) {
-        return new JavaParserSymbolDeclaration(variableDeclarator, variableDeclarator.getName().getId(), typeSolver, false, false, true);
+        return new JavaParserSymbolDeclaration(variableDeclarator, variableDeclarator.getName().getId(), typeSolver);
     }
 
     public static int getParamPos(Parameter parameter) {
@@ -105,12 +103,12 @@
 
     @Override
     public boolean isField() {
-        return field;
+        return false;
     }
 
     @Override
     public boolean isParameter() {
-        return parameter;
+        return false;
     }
 
     @Override
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java
index 198083f..33be548 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java
@@ -25,8 +25,6 @@
 import java.util.List;
 import java.util.Optional;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
-
 /**
  * @author Federico Tomassetti
  */
@@ -41,15 +39,15 @@
     }
 
     public String getPackageName() {
-        return Helper.getPackageName(wrappedNode);
+        return AstResolutionUtils.getPackageName(wrappedNode);
     }
 
     public String getClassName() {
-        return Helper.getClassName("", wrappedNode);
+        return AstResolutionUtils.getClassName("", wrappedNode);
     }
 
     public String getQualifiedName() {
-        String containerName = Helper.containerName(getParentNode(wrappedNode));
+        String containerName = AstResolutionUtils.containerName(wrappedNode.getParentNode().orElse(null));
         if (containerName.isEmpty()) {
             return wrappedNode.getName().getId();
         } else {
@@ -80,7 +78,16 @@
         }
     }
 
-    public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    /**
+     * This method is deprecated because it receives the TypesSolver as a parameter.
+     * Eventually we would like to remove all usages of TypeSolver as a parameter.
+     *
+     * Also, resolution should move out of declarations, so that they are pure declarations and the resolution should
+     * work for JavaParser, Reflection and Javassist classes in the same way and not be specific to the three
+     * implementations.
+     */
+    @Deprecated
+    public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
         if(wrappedNode instanceof NodeWithTypeParameters<?>) {
             NodeList<TypeParameter> typeParameters = ((NodeWithTypeParameters<?>) wrappedNode).getTypeParameters();
             for (com.github.javaparser.ast.type.TypeParameter typeParameter : typeParameters) {
@@ -90,14 +97,18 @@
             }
         }
 
-        // Internal classes
+        // Member classes & interfaces
         for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) {
             if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
                 com.github.javaparser.ast.body.TypeDeclaration<?> internalType = (com.github.javaparser.ast.body.TypeDeclaration<?>) member;
                 String prefix = internalType.getName() + ".";
                 if (internalType.getName().getId().equals(name)) {
                     if (internalType instanceof ClassOrInterfaceDeclaration) {
-                        return SymbolReference.solved(new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver));
+                        if (((ClassOrInterfaceDeclaration) internalType).isInterface()) {
+                            return SymbolReference.solved(new JavaParserInterfaceDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver));
+                        } else {
+                            return SymbolReference.solved(new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver));
+                        }
                     } else if (internalType instanceof EnumDeclaration) {
                         return SymbolReference.solved(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver));
                     } else {
@@ -105,7 +116,11 @@
                     }
                 } else if (name.startsWith(prefix) && name.length() > prefix.length()) {
                     if (internalType instanceof ClassOrInterfaceDeclaration) {
-                        return new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
+                        if (((ClassOrInterfaceDeclaration) internalType).isInterface()) {
+                            return new JavaParserInterfaceDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length()));
+                        } else {
+                            return new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length()));
+                        }
                     } else if (internalType instanceof EnumDeclaration) {
                         return new SymbolSolver(typeSolver).solveTypeInType(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver), name.substring(prefix.length()));
                     } else {
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java
index 0d1f42e..3c9895f 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java
@@ -57,7 +57,7 @@
     }
 
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes) {
-        return getContext().solveMethod(name, parameterTypes, false, typeSolver);
+        return getContext().solveMethod(name, parameterTypes, false);
     }
 
     @Override
@@ -121,7 +121,7 @@
             return JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration);
         } else if (parentNode instanceof com.github.javaparser.ast.body.ConstructorDeclaration){
             com.github.javaparser.ast.body.ConstructorDeclaration jpConstructorDeclaration = (com.github.javaparser.ast.body.ConstructorDeclaration) parentNode;
-            Optional<ClassOrInterfaceDeclaration> jpTypeDeclaration = jpConstructorDeclaration.getAncestorOfType(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class);
+            Optional<ClassOrInterfaceDeclaration> jpTypeDeclaration = jpConstructorDeclaration.findAncestor(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class);
             if (jpTypeDeclaration.isPresent()) {
                 ResolvedReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration.get());
                 if (typeDeclaration.isClass()) {
@@ -179,7 +179,7 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         throw new UnsupportedOperationException();
     }
 
@@ -220,4 +220,9 @@
         }
         return Optional.empty();
     }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java
index a602ebf..4852c5f 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java
@@ -18,10 +18,7 @@
 
 import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.type.TypeParameter;
-import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
+import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
@@ -56,12 +53,12 @@
 
     @Override
     public String getPackageName() {
-        return Helper.getPackageName(wrappedNode);
+        return AstResolutionUtils.getPackageName(wrappedNode);
     }
 
     @Override
     public String getClassName() {
-        return Helper.getClassName("", wrappedNode);
+        return AstResolutionUtils.getClassName("", wrappedNode);
     }
 
     @Override
@@ -118,7 +115,7 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         throw new UnsupportedOperationException();
     }
 
@@ -184,4 +181,9 @@
     public Optional<ResolvedReferenceTypeDeclaration> containerType() {
         return asTypeParameter().containerType();
     }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserVariableDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserVariableDeclaration.java
new file mode 100644
index 0000000..17f81a5
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserVariableDeclaration.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserVariableDeclaration implements ResolvedValueDeclaration {
+
+    private VariableDeclarator variableDeclarator;
+    private VariableDeclarationExpr wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserVariableDeclaration(VariableDeclarator variableDeclarator, TypeSolver typeSolver) {
+        if (typeSolver == null) {
+            throw new IllegalArgumentException("typeSolver should not be null");
+        }
+        this.variableDeclarator = variableDeclarator;
+        this.typeSolver = typeSolver;
+        if (!(requireParentNode(variableDeclarator) instanceof VariableDeclarationExpr)) {
+            throw new IllegalStateException(requireParentNode(variableDeclarator).getClass().getCanonicalName());
+        }
+        this.wrappedNode = (VariableDeclarationExpr) requireParentNode(variableDeclarator);
+    }
+
+    @Override
+    public ResolvedType getType() {
+        return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), wrappedNode);
+    }
+
+    @Override
+    public String getName() {
+        return variableDeclarator.getName().getId();
+    }
+
+    @Override
+    public boolean isVariable() {
+        return true;
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserFieldDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public VariableDeclarationExpr getWrappedNode() {
+        return wrappedNode;
+    }
+
+    public VariableDeclarator getVariableDeclarator() {
+        return variableDeclarator;
+    }
+
+    @Override
+    public String toString() {
+        return "JavaParserVariableDeclaration{" + getName() + "}";
+    }
+
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java
index 88865de..f7c6ff5 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java
@@ -26,8 +26,6 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
-import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
-
 /**
  * @author Federico Tomassetti
  */
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationDeclaration.java
new file mode 100644
index 0000000..f278284
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationDeclaration.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.resolution.declarations.*;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import javassist.CtClass;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @author Malte Skoruppa
+ */
+public class JavassistAnnotationDeclaration extends AbstractTypeDeclaration implements ResolvedAnnotationDeclaration {
+
+    private CtClass ctClass;
+    private TypeSolver typeSolver;
+    private JavassistTypeDeclarationAdapter javassistTypeDeclarationAdapter;
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+                "ctClass=" + ctClass.getName() +
+                ", typeSolver=" + typeSolver +
+                '}';
+    }
+
+    public JavassistAnnotationDeclaration(CtClass ctClass, TypeSolver typeSolver) {
+        if (!ctClass.isAnnotation()) {
+            throw new IllegalArgumentException("Not an annotation: " + ctClass.getName());
+        }
+        this.ctClass = ctClass;
+        this.typeSolver = typeSolver;
+        this.javassistTypeDeclarationAdapter = new JavassistTypeDeclarationAdapter(ctClass, typeSolver);
+    }
+
+    @Override
+    public String getPackageName() {
+        return ctClass.getPackageName();
+    }
+
+    @Override
+    public String getClassName() {
+        String qualifiedName = getQualifiedName();
+        if (qualifiedName.contains(".")) {
+            return qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1, qualifiedName.length());
+        } else {
+            return qualifiedName;
+        }
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return ctClass.getName().replace('$', '.');
+    }
+
+    @Override
+    public boolean isAssignableBy(ResolvedType type) {
+        // TODO #1836
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<ResolvedFieldDeclaration> getAllFields() {
+        // TODO #1837
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<ResolvedMethodDeclaration> getDeclaredMethods() {
+        // TODO #1838
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        return ctClass.hasAnnotation(canonicalName);
+    }
+
+    @Override
+    public String getName() {
+        return getClassName();
+    }
+
+    /**
+     * Annotation declarations cannot have type parameters and hence this method always returns an empty list.
+     *
+     * @return An empty list.
+     */
+    @Override
+    public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
+        // Annotation declarations cannot have type parameters - i.e. we can always return an empty list.
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Optional<ResolvedReferenceTypeDeclaration> containerType() {
+        // TODO #1841
+        throw new UnsupportedOperationException("containerType() is not supported for " + this.getClass().getCanonicalName());
+    }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<ResolvedAnnotationMemberDeclaration> getAnnotationMembers() {
+        return Stream.of(ctClass.getDeclaredMethods())
+                .map(m -> new JavassistAnnotationMemberDeclaration(m, typeSolver))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public Optional<AnnotationDeclaration> toAst() {
+        return Optional.empty();
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationMemberDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationMemberDeclaration.java
new file mode 100644
index 0000000..6eaa7e7
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistAnnotationMemberDeclaration.java
@@ -0,0 +1,40 @@
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.resolution.declarations.ResolvedAnnotationMemberDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import javassist.CtMethod;
+
+/**
+ * @author Malte Skoruppa
+ */
+public class JavassistAnnotationMemberDeclaration implements ResolvedAnnotationMemberDeclaration {
+
+    private CtMethod annotationMember;
+    private TypeSolver typeSolver;
+
+    public JavassistAnnotationMemberDeclaration(CtMethod annotationMember, TypeSolver typeSolver) {
+        this.annotationMember = annotationMember;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public Expression getDefaultValue() {
+        // TODO we should do something like this:
+        // AnnotationDefaultAttribute defaultAttribute = (AnnotationDefaultAttribute) annotationMember.getMethodInfo().getAttribute(AnnotationDefaultAttribute.tag);
+        // return defaultAttribute != null ? defaultAttribute.getDefaultValue() : null;
+        // TODO ...but the interface wants us to return a JavaParser Expression node.
+        throw new UnsupportedOperationException("Obtaining the default value of a library annotation member is not supported yet.");
+    }
+
+    @Override
+    public ResolvedType getType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName() {
+        return annotationMember.getName();
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java
index 6c516b5..fbd0b32 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java
@@ -24,6 +24,7 @@
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
 import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
@@ -48,9 +49,7 @@
 /**
  * @author Federico Tomassetti
  */
-public class JavassistClassDeclaration extends AbstractClassDeclaration {
-
-
+public class JavassistClassDeclaration extends AbstractClassDeclaration implements MethodUsageResolutionCapability {
 
     private CtClass ctClass;
     private TypeSolver typeSolver;
@@ -75,7 +74,7 @@
 
     @Override
     public boolean hasDirectlyAnnotation(String canonicalName) {
-        throw new UnsupportedOperationException();
+        return ctClass.hasAnnotation(canonicalName);
     }
 
     @Override
@@ -95,9 +94,7 @@
 
         JavassistClassDeclaration that = (JavassistClassDeclaration) o;
 
-        if (!ctClass.equals(that.ctClass)) return false;
-
-        return true;
+        return ctClass.equals(that.ctClass);
     }
 
     @Override
@@ -114,7 +111,7 @@
     public String getClassName() {
         String className = ctClass.getName().replace('$', '.');
         if (getPackageName() != null) {
-            return className.substring(getPackageName().length() + 1, className.length());
+            return className.substring(getPackageName().length() + 1);
         }
         return className;
     }
@@ -124,9 +121,10 @@
         return ctClass.getName().replace('$', '.');
     }
 
-    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
+    @Deprecated
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes,
                                                     Context invokationContext, List<ResolvedType> typeParameterValues) {
-        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
+        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues);
     }
 
     @Deprecated
@@ -138,14 +136,14 @@
         }
 
         final String superclassFQN = getSuperclassFQN();
-        SymbolReference<? extends ResolvedValueDeclaration> ref = solveSymbolForFQN(name, typeSolver, superclassFQN);
+        SymbolReference<? extends ResolvedValueDeclaration> ref = solveSymbolForFQN(name, superclassFQN);
         if (ref.isSolved()) {
             return ref;
         }
 
         String[] interfaceFQNs = getInterfaceFQNs();
         for (String interfaceFQN : interfaceFQNs) {
-            SymbolReference<? extends ResolvedValueDeclaration> interfaceRef = solveSymbolForFQN(name, typeSolver, interfaceFQN);
+            SymbolReference<? extends ResolvedValueDeclaration> interfaceRef = solveSymbolForFQN(name, interfaceFQN);
             if (interfaceRef.isSolved()) {
                 return interfaceRef;
             }
@@ -154,7 +152,7 @@
         return SymbolReference.unsolved(ResolvedValueDeclaration.class);
     }
 
-    private SymbolReference<? extends ResolvedValueDeclaration> solveSymbolForFQN(String symbolName, TypeSolver typeSolver, String fqn) {
+    private SymbolReference<? extends ResolvedValueDeclaration> solveSymbolForFQN(String symbolName, String fqn) {
         if (fqn == null) {
             return SymbolReference.unsolved(ResolvedValueDeclaration.class);
         }
@@ -172,48 +170,64 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
-        List<ResolvedReferenceType> ancestors = new LinkedList<>();
-        if (getSuperClass() != null) {
-            ancestors.add(getSuperClass());
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
+        List<ResolvedReferenceType> ancestors = new ArrayList<>();
+        try {
+            ResolvedReferenceType superClass = getSuperClass();
+            if (superClass != null) {
+                ancestors.add(superClass);
+            }
+        } catch (UnsolvedSymbolException e) {
+            if (!acceptIncompleteList) {
+                // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully
+                throw e;
+            }
         }
-        ancestors.addAll(getInterfaces());
+        try {
+            ancestors.addAll(getInterfaces());
+        } catch (UnsolvedSymbolException e) {
+            if (!acceptIncompleteList) {
+                // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully
+                throw e;
+            }
+        }
         return ancestors;
     }
 
+    @Override
     @Deprecated
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
         List<ResolvedMethodDeclaration> candidates = new ArrayList<>();
         Predicate<CtMethod> staticOnlyCheck = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
         for (CtMethod method : ctClass.getDeclaredMethods()) {
             boolean isSynthetic = method.getMethodInfo().getAttribute(SyntheticAttribute.tag) != null;
-            boolean isNotBridge =  (method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0;
+            boolean isNotBridge = (method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0;
             if (method.getName().equals(name) && !isSynthetic && isNotBridge && staticOnlyCheck.test(method)) {
-                candidates.add(new JavassistMethodDeclaration(method, typeSolver));
+                ResolvedMethodDeclaration candidate = new JavassistMethodDeclaration(method, typeSolver);
+                candidates.add(candidate);
+
+                // no need to search for overloaded/inherited methods if the method has no parameters
+                if (argumentsTypes.isEmpty() && candidate.getNumberOfParams() == 0) {
+                    return SymbolReference.solved(candidate);
+                }
             }
         }
 
-        try {
-            CtClass superClass = ctClass.getSuperclass();
-            if (superClass != null) {
-                SymbolReference<ResolvedMethodDeclaration> ref = new JavassistClassDeclaration(superClass, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
-                if (ref.isSolved()) {
-                    candidates.add(ref.getCorrespondingDeclaration());
-                }
-            }
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e);
+        // add the method declaration of the superclass to the candidates, if present
+        SymbolReference<ResolvedMethodDeclaration> superClassMethodRef = MethodResolutionLogic
+                .solveMethodInType(getSuperClass().getTypeDeclaration(), name, argumentsTypes, staticOnly);
+        if (superClassMethodRef.isSolved()) {
+            candidates.add(superClassMethodRef.getCorrespondingDeclaration());
         }
 
-        try {
-            for (CtClass interfaze : ctClass.getInterfaces()) {
-                SymbolReference<ResolvedMethodDeclaration> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
-                if (ref.isSolved()) {
-                    candidates.add(ref.getCorrespondingDeclaration());
-                }
+        // add the method declaration of the interfaces to the candidates, if present
+        for (ResolvedReferenceType interfaceRef : getInterfaces()) {
+            SymbolReference<ResolvedMethodDeclaration> interfaceMethodRef =
+                    MethodResolutionLogic.solveMethodInType(interfaceRef.getTypeDeclaration(), name, argumentsTypes,
+                                                            staticOnly);
+            if (interfaceMethodRef.isSolved()) {
+                candidates.add(interfaceMethodRef.getCorrespondingDeclaration());
             }
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e);
         }
 
         return MethodResolutionLogic.findMostApplicable(candidates, name, argumentsTypes, typeSolver);
@@ -260,7 +274,7 @@
 
     @Override
     public List<ResolvedFieldDeclaration> getAllFields() {
-      return javassistTypeDeclarationAdapter.getDeclaredFields();
+        return javassistTypeDeclarationAdapter.getDeclaredFields();
     }
 
     @Override
@@ -292,17 +306,15 @@
     @Override
     public ResolvedReferenceType getSuperClass() {
         try {
-            if (ctClass.getSuperclass() == null) {
+            if (ctClass.getClassFile().getSuperclass() == null) {
                 return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
             }
             if (ctClass.getGenericSignature() == null) {
-                return new ReferenceTypeImpl(new JavassistClassDeclaration(ctClass.getSuperclass(), typeSolver), typeSolver);
+                return new ReferenceTypeImpl(typeSolver.solveType(JavassistUtils.internalNameToCanonicalName(ctClass.getClassFile().getSuperclass())), typeSolver);
             }
 
             SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature());
             return JavassistUtils.signatureTypeToType(classSignature.getSuperClass(), typeSolver, this).asReferenceType();
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e);
         } catch (BadBytecode e) {
             throw new RuntimeException(e);
         }
@@ -312,8 +324,8 @@
     public List<ResolvedReferenceType> getInterfaces() {
         try {
             if (ctClass.getGenericSignature() == null) {
-                return Arrays.stream(ctClass.getInterfaces())
-                        .map(i -> new JavassistInterfaceDeclaration(i, typeSolver))
+                return Arrays.stream(ctClass.getClassFile().getInterfaces())
+                        .map(i -> typeSolver.solveType(JavassistUtils.internalNameToCanonicalName(i)))
                         .map(i -> new ReferenceTypeImpl(i, typeSolver))
                         .collect(Collectors.toList());
             } else {
@@ -322,8 +334,6 @@
                         .map(i -> JavassistUtils.signatureTypeToType(i, typeSolver, this).asReferenceType())
                         .collect(Collectors.toList());
             }
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e);
         } catch (BadBytecode e) {
             throw new RuntimeException(e);
         }
@@ -351,7 +361,7 @@
 
     @Override
     public List<ResolvedConstructorDeclaration> getConstructors() {
-      return javassistTypeDeclarationAdapter.getConstructors();
+        return javassistTypeDeclarationAdapter.getConstructors();
     }
 
     @Override
@@ -392,4 +402,9 @@
          */
         return this.internalTypes().stream().anyMatch(f -> f.getName().endsWith(name));
     }
+
+    @Override
+    public Optional<Node> toAst() {
+        return Optional.empty();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration.java
index 0fd010a..720abb4 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration.java
@@ -17,25 +17,27 @@
 package com.github.javaparser.symbolsolver.javassistmodel;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import javassist.CtConstructor;
 import javassist.NotFoundException;
-import javassist.bytecode.BadBytecode;
-import javassist.bytecode.SignatureAttribute;
+import javassist.bytecode.*;
 
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
  * @author Fred Lefévère-Laoide
  */
 public class JavassistConstructorDeclaration implements ResolvedConstructorDeclaration {
-    private CtConstructor ctConstructor;
-    private TypeSolver typeSolver;
+    private final CtConstructor ctConstructor;
+    private final TypeSolver typeSolver;
 
     public JavassistConstructorDeclaration(CtConstructor ctConstructor, TypeSolver typeSolver) {
         this.ctConstructor = ctConstructor;
@@ -44,8 +46,9 @@
 
     @Override
     public String toString() {
-        return "JavassistMethodDeclaration{" +
-                "CtConstructor=" + ctConstructor +
+        return getClass().getSimpleName() + "{" +
+                "ctConstructor=" + ctConstructor.getName() +
+                ", typeSolver=" + typeSolver +
                 '}';
     }
 
@@ -90,12 +93,15 @@
             if ((ctConstructor.getModifiers() & javassist.Modifier.VARARGS) > 0) {
                 variadic = i == (ctConstructor.getParameterTypes().length - 1);
             }
+            Optional<String> paramName = JavassistUtils.extractParameterName(ctConstructor, i);
             if (ctConstructor.getGenericSignature() != null) {
                 SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctConstructor.getGenericSignature());
                 SignatureAttribute.Type signatureType = methodSignature.getParameterTypes()[i];
-                return new JavassistParameterDeclaration(JavassistUtils.signatureTypeToType(signatureType, typeSolver, this), typeSolver, variadic);
+                return new JavassistParameterDeclaration(JavassistUtils.signatureTypeToType(signatureType,
+                        typeSolver, this), typeSolver, variadic, paramName.orElse(null));
             } else {
-                return new JavassistParameterDeclaration(ctConstructor.getParameterTypes()[i], typeSolver, variadic);
+                return new JavassistParameterDeclaration(ctConstructor.getParameterTypes()[i], typeSolver, variadic,
+                        paramName.orElse(null));
             }
         } catch (NotFoundException e) {
             throw new RuntimeException(e);
@@ -143,4 +149,9 @@
             throw new RuntimeException(e);
         }
     }
+
+    @Override
+    public Optional<ConstructorDeclaration> toAst() {
+        return Optional.empty();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumConstantDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumConstantDeclaration.java
index 178c74b..0ac6bef 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumConstantDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumConstantDeclaration.java
@@ -19,6 +19,7 @@
 import com.github.javaparser.resolution.declarations.ResolvedEnumConstantDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import javassist.CtField;
 import javassist.bytecode.AccessFlag;
 
@@ -29,13 +30,16 @@
 
     private CtField ctField;
     private TypeSolver typeSolver;
+    private ResolvedType type;
 
     public JavassistEnumConstantDeclaration(CtField ctField, TypeSolver typeSolver) {
         if (ctField == null) {
             throw new IllegalArgumentException();
         }
-        if ((ctField.getFieldInfo2().getAccessFlags() & AccessFlag.ENUM) != 0) {
-            throw new IllegalArgumentException("Trying to instantiate a JavassistEnumConstantDeclaration with something which is not an enum field: " + ctField.toString());
+        if ((ctField.getFieldInfo2().getAccessFlags() & AccessFlag.ENUM) == 0) {
+            throw new IllegalArgumentException(
+                    "Trying to instantiate a JavassistEnumConstantDeclaration with something which is not an enum field: "
+                            + ctField.toString());
         }
         this.ctField = ctField;
         this.typeSolver = typeSolver;
@@ -49,6 +53,19 @@
 
     @Override
     public ResolvedType getType() {
-        throw new UnsupportedOperationException();
+        if (type == null) {
+            type = new ReferenceTypeImpl(new JavassistEnumDeclaration(ctField.getDeclaringClass(), typeSolver),
+                    typeSolver);
+        }
+        return type;
     }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+                "ctField=" + ctField.getName() +
+                ", typeSolver=" + typeSolver +
+                '}';
+    }
+
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java
index 9a54a09..e398f7b 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java
@@ -17,16 +17,18 @@
 package com.github.javaparser.symbolsolver.javassistmodel;
 
 import com.github.javaparser.ast.AccessSpecifier;
-import com.github.javaparser.ast.expr.MethodCallExpr;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.logic.MethodResolutionCapability;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
 import javassist.CtClass;
@@ -44,7 +46,8 @@
 /**
  * @author Federico Tomassetti
  */
-public class JavassistEnumDeclaration extends AbstractTypeDeclaration implements ResolvedEnumDeclaration {
+public class JavassistEnumDeclaration extends AbstractTypeDeclaration
+        implements ResolvedEnumDeclaration, MethodResolutionCapability, MethodUsageResolutionCapability {
 
     private CtClass ctClass;
     private TypeSolver typeSolver;
@@ -76,7 +79,7 @@
     public String getClassName() {
         String name = ctClass.getName().replace('$', '.');
         if (getPackageName() != null) {
-            return name.substring(getPackageName().length() + 1, name.length());
+            return name.substring(getPackageName().length() + 1);
         }
         return name;
     }
@@ -87,30 +90,32 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         // Direct ancestors of an enum are java.lang.Enum and interfaces
-        List<ResolvedReferenceType> ancestors = new LinkedList<>();
+        List<ResolvedReferenceType> ancestors = new ArrayList<>();
 
-        try {
-            CtClass superClass = ctClass.getSuperclass();
+        String superClassName = ctClass.getClassFile().getSuperclass();
 
-            if (superClass != null) {
-                ResolvedType superClassTypeUsage = JavassistFactory.typeUsageFor(superClass, typeSolver);
-
-                if (superClassTypeUsage.isReferenceType()) {
-                    ancestors.add(superClassTypeUsage.asReferenceType());
+        if (superClassName != null) {
+            try {
+                ancestors.add(new ReferenceTypeImpl(typeSolver.solveType(superClassName), typeSolver));
+            } catch (UnsolvedSymbolException e) {
+                if (!acceptIncompleteList) {
+                    // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully
+                    throw e;
                 }
             }
+        }
 
-            for (CtClass interfaze : ctClass.getInterfaces()) {
-                ResolvedType interfazeTypeUsage = JavassistFactory.typeUsageFor(interfaze, typeSolver);
-
-                if (interfazeTypeUsage.isReferenceType()) {
-                    ancestors.add(interfazeTypeUsage.asReferenceType());
+        for (String interfazeName : ctClass.getClassFile().getInterfaces()) {
+            try {
+                ancestors.add(new ReferenceTypeImpl(typeSolver.solveType(interfazeName), typeSolver));
+            } catch (UnsolvedSymbolException e) {
+                if (!acceptIncompleteList) {
+                    // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully
+                    throw e;
                 }
             }
-        } catch (NotFoundException e) {
-            throw new RuntimeException("Ancestor not found for " + ctClass.getName() + ".", e);
         }
 
         return ancestors;
@@ -150,7 +155,7 @@
 
     @Override
     public boolean hasDirectlyAnnotation(String canonicalName) {
-        throw new UnsupportedOperationException();
+        return ctClass.hasAnnotation(canonicalName);
     }
 
     @Override
@@ -169,6 +174,7 @@
         return javassistTypeDeclarationAdapter.containerType();
     }
 
+    @Override
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
         List<ResolvedMethodDeclaration> candidates = new ArrayList<>();
         Predicate<CtMethod> staticOnlyCheck = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
@@ -195,9 +201,9 @@
         return MethodResolutionLogic.findMostApplicable(candidates, name, argumentsTypes, typeSolver);
     }
 
-    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes,
                                                     Context invokationContext, List<ResolvedType> typeParameterValues) {
-        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
+        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues);
     }
 
     @Override
@@ -243,7 +249,7 @@
 
         String[] interfaceFQNs = getInterfaceFQNs();
         for (String interfaceFQN : interfaceFQNs) {
-            SymbolReference<? extends ResolvedValueDeclaration> interfaceRef = solveSymbolForFQN(name, typeSolver, interfaceFQN);
+            SymbolReference<? extends ResolvedValueDeclaration> interfaceRef = solveSymbolForFQN(name, interfaceFQN);
             if (interfaceRef.isSolved()) {
                 return interfaceRef;
             }
@@ -252,7 +258,7 @@
         return SymbolReference.unsolved(ResolvedValueDeclaration.class);
     }
 
-    private SymbolReference<? extends ResolvedValueDeclaration> solveSymbolForFQN(String symbolName, TypeSolver typeSolver, String fqn) {
+    private SymbolReference<? extends ResolvedValueDeclaration> solveSymbolForFQN(String symbolName, String fqn) {
         if (fqn == null) {
             return SymbolReference.unsolved(ResolvedValueDeclaration.class);
         }
@@ -272,4 +278,17 @@
                 .map(f -> new JavassistEnumConstantDeclaration(f, typeSolver))
                 .collect(Collectors.toList());
     }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return javassistTypeDeclarationAdapter.getConstructors();
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+                "ctClass=" + ctClass.getName() +
+                ", typeSolver=" + typeSolver +
+                '}';
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java
index 1188b9b..82170f9 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java
@@ -57,12 +57,12 @@
   }
 
   public static ResolvedReferenceTypeDeclaration toTypeDeclaration(CtClass ctClazz, TypeSolver typeSolver) {
-    if (ctClazz.isInterface()) {
+    if (ctClazz.isAnnotation()) {
+      return new JavassistAnnotationDeclaration(ctClazz, typeSolver);
+    } else if (ctClazz.isInterface()) {
       return new JavassistInterfaceDeclaration(ctClazz, typeSolver);
     } else if (ctClazz.isEnum()) {
       return new JavassistEnumDeclaration(ctClazz, typeSolver);
-    } else if (ctClazz.isAnnotation()) {
-      throw new UnsupportedOperationException("CtClass of annotation not yet supported");
     } else if (ctClazz.isArray()) {
       throw new IllegalArgumentException("This method should not be called passing an array");
     } else {
@@ -78,7 +78,7 @@
     } else if (Modifier.isPrivate(modifiers)) {
       return AccessSpecifier.PRIVATE;
     } else {
-      return AccessSpecifier.DEFAULT;
+      return AccessSpecifier.PACKAGE_PRIVATE;
     }
   }
 
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration.java
index 85958ca..b9902b2 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration.java
@@ -50,9 +50,7 @@
             } else {
                 return JavassistFactory.typeUsageFor(ctField.getType(), typeSolver);
             }
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e);
-        } catch (BadBytecode e) {
+        } catch (NotFoundException | BadBytecode e) {
             throw new RuntimeException(e);
         }
     }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java
index 9637535..5777172 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java
@@ -17,13 +17,16 @@
 package com.github.javaparser.symbolsolver.javassistmodel;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.logic.MethodResolutionCapability;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
@@ -44,7 +47,8 @@
 /**
  * @author Federico Tomassetti
  */
-public class JavassistInterfaceDeclaration extends AbstractTypeDeclaration implements ResolvedInterfaceDeclaration {
+public class JavassistInterfaceDeclaration extends AbstractTypeDeclaration
+        implements ResolvedInterfaceDeclaration, MethodResolutionCapability, MethodUsageResolutionCapability {
 
     private CtClass ctClass;
     private TypeSolver typeSolver;
@@ -69,12 +73,8 @@
 
     @Override
     public List<ResolvedReferenceType> getInterfacesExtended() {
-        try {
-            return Arrays.stream(ctClass.getInterfaces()).map(i -> new JavassistInterfaceDeclaration(i, typeSolver))
-                    .map(i -> new ReferenceTypeImpl(i, typeSolver)).collect(Collectors.toList());
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e);
-        }
+        return Arrays.stream(ctClass.getClassFile().getInterfaces()).map(i -> typeSolver.solveType(i))
+                .map(i -> new ReferenceTypeImpl(i, typeSolver)).collect(Collectors.toList());
     }
 
     @Override
@@ -86,7 +86,7 @@
     public String getClassName() {
         String className = ctClass.getName().replace('$', '.');
         if (getPackageName() != null) {
-            return className.substring(getPackageName().length() + 1, className.length());
+            return className.substring(getPackageName().length() + 1);
         }
         return className;
     }
@@ -97,12 +97,13 @@
     }
 
     @Deprecated
-    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes,
                                                     Context invokationContext, List<ResolvedType> typeParameterValues) {
 
-        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
+        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues);
     }
 
+    @Override
     @Deprecated
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
         List<ResolvedMethodDeclaration> candidates = new ArrayList<>();
@@ -157,17 +158,24 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
         List<ResolvedReferenceType> ancestors = new ArrayList<>();
         try {
             for (CtClass interfaze : ctClass.getInterfaces()) {
-                ResolvedReferenceType superInterfaze = JavassistFactory.typeUsageFor(interfaze, typeSolver).asReferenceType();
-                ancestors.add(superInterfaze);
+                try {
+                    ResolvedReferenceType superInterfaze = JavassistFactory.typeUsageFor(interfaze, typeSolver).asReferenceType();
+                    ancestors.add(superInterfaze);
+                } catch (UnsolvedSymbolException e) {
+                    if (!acceptIncompleteList) {
+                        // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully
+                        throw e;
+                    }
+                }
             }
         } catch (NotFoundException e) {
             throw new RuntimeException(e);
         }
-        ancestors = ancestors.stream().filter(a -> a.getQualifiedName() != Object.class.getCanonicalName())
+        ancestors = ancestors.stream().filter(a -> !a.getQualifiedName().equals(Object.class.getCanonicalName()))
                 .collect(Collectors.toList());
         ancestors.add(new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver));
         return ancestors;
@@ -182,19 +190,7 @@
 
     @Override
     public boolean hasDirectlyAnnotation(String canonicalName) {
-        try {
-            for (Object annotationRaw : ctClass.getAnnotations()) {
-                if (annotationRaw.getClass().getCanonicalName().equals(canonicalName)) {
-                    return true;
-                }
-                if (Arrays.stream(annotationRaw.getClass().getInterfaces()).anyMatch(it -> it.getCanonicalName().equals(canonicalName))) {
-                    return true;
-                }
-            }
-        } catch (ClassNotFoundException e) {
-            throw new RuntimeException(e);
-        }
-        return false;
+        return ctClass.hasAnnotation(canonicalName);
     }
 
     @Override
@@ -229,7 +225,7 @@
 
         String[] interfaceFQNs = getInterfaceFQNs();
         for (String interfaceFQN : interfaceFQNs) {
-            SymbolReference<? extends ResolvedValueDeclaration> interfaceRef = solveSymbolForFQN(name, typeSolver, interfaceFQN);
+            SymbolReference<? extends ResolvedValueDeclaration> interfaceRef = solveSymbolForFQN(name, interfaceFQN);
             if (interfaceRef.isSolved()) {
                 return interfaceRef;
             }
@@ -238,7 +234,7 @@
         return SymbolReference.unsolved(ResolvedValueDeclaration.class);
     }
 
-    private SymbolReference<? extends ResolvedValueDeclaration> solveSymbolForFQN(String symbolName, TypeSolver typeSolver, String fqn) {
+    private SymbolReference<? extends ResolvedValueDeclaration> solveSymbolForFQN(String symbolName, String fqn) {
         if (fqn == null) {
             return SymbolReference.unsolved(ResolvedValueDeclaration.class);
         }
@@ -289,4 +285,14 @@
          */
         return this.internalTypes().stream().anyMatch(f -> f.getName().endsWith(name));
     }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Optional<ClassOrInterfaceDeclaration> toAst() {
+        return Optional.empty();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java
index c474d50..2cd2c98 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java
@@ -18,6 +18,7 @@
 
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration;
@@ -25,6 +26,7 @@
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.TypeVariableResolutionCapability;
 import com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import javassist.CtMethod;
@@ -33,15 +35,13 @@
 import javassist.bytecode.SignatureAttribute;
 
 import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
  * @author Federico Tomassetti
  */
-public class JavassistMethodDeclaration implements ResolvedMethodDeclaration {
+public class JavassistMethodDeclaration implements ResolvedMethodDeclaration, TypeVariableResolutionCapability {
     private CtMethod ctMethod;
     private TypeSolver typeSolver;
 
@@ -91,6 +91,8 @@
     public ResolvedReferenceTypeDeclaration declaringType() {
         if (ctMethod.getDeclaringClass().isInterface()) {
             return new JavassistInterfaceDeclaration(ctMethod.getDeclaringClass(), typeSolver);
+        } else if (ctMethod.getDeclaringClass().isEnum()) {
+            return new JavassistEnumDeclaration(ctMethod.getDeclaringClass(), typeSolver);
         } else {
             return new JavassistClassDeclaration(ctMethod.getDeclaringClass(), typeSolver);
         }
@@ -105,9 +107,7 @@
             } else {
                 return JavassistFactory.typeUsageFor(ctMethod.getReturnType(), typeSolver);
             }
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e);
-        } catch (BadBytecode e) {
+        } catch (NotFoundException | BadBytecode e) {
             throw new RuntimeException(e);
         }
     }
@@ -129,17 +129,15 @@
             if ((ctMethod.getModifiers() & javassist.Modifier.VARARGS) > 0) {
                 variadic = i == (ctMethod.getParameterTypes().length - 1);
             }
-            if (ctMethod.getGenericSignature() != null) {
-                SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctMethod.getGenericSignature());
-                SignatureAttribute.Type signatureType = methodSignature.getParameterTypes()[i];
-                return new JavassistParameterDeclaration(JavassistUtils.signatureTypeToType(signatureType, typeSolver, this), typeSolver, variadic);
-            } else {
-                return new JavassistParameterDeclaration(ctMethod.getParameterTypes()[i], typeSolver, variadic);
-            }
-        } catch (NotFoundException e) {
+            Optional<String> paramName = JavassistUtils.extractParameterName(ctMethod, i);
+            String signature = ctMethod.getGenericSignature() == null ? ctMethod.getSignature() : ctMethod.getGenericSignature();
+            SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(signature);
+            SignatureAttribute.Type signatureType = methodSignature.getParameterTypes()[i];
+            return new JavassistParameterDeclaration(JavassistUtils.signatureTypeToType(signatureType,
+                    typeSolver, this), typeSolver, variadic, paramName.orElse(null));
+
+        } catch (NotFoundException | BadBytecode e) {
             throw new RuntimeException(e);
-        } catch (BadBytecode badBytecode) {
-            throw new RuntimeException(badBytecode);
         }
     }
 
@@ -160,7 +158,7 @@
     public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
         try {
             if (ctMethod.getGenericSignature() == null) {
-                return Collections.emptyList();
+                return new ArrayList<>();
             }
             SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctMethod.getGenericSignature());
             return Arrays.stream(methodSignature.getTypeParameters()).map((jasTp) -> new JavassistTypeParameter(jasTp, this, typeSolver)).collect(Collectors.toList());
@@ -171,7 +169,7 @@
 
     @Override
     public AccessSpecifier accessSpecifier() {
-        throw new UnsupportedOperationException();
+        return JavassistFactory.modifiersToAccessLevel(ctMethod.getModifiers());
     }
 
     @Override
@@ -195,4 +193,9 @@
             throw new RuntimeException(e);
         }
     }
+
+    @Override
+    public Optional<MethodDeclaration> toAst() {
+        return Optional.empty();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration.java
index 4b3e14e..d84c4d2 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration.java
@@ -28,12 +28,14 @@
     private ResolvedType type;
     private TypeSolver typeSolver;
     private boolean variadic;
+    private String name;
 
-    public JavassistParameterDeclaration(CtClass type, TypeSolver typeSolver, boolean variadic) {
-        this(JavassistFactory.typeUsageFor(type, typeSolver), typeSolver, variadic);
+    public JavassistParameterDeclaration(CtClass type, TypeSolver typeSolver, boolean variadic, String name) {
+        this(JavassistFactory.typeUsageFor(type, typeSolver), typeSolver, variadic, name);
     }
 
-    public JavassistParameterDeclaration(ResolvedType type, TypeSolver typeSolver, boolean variadic) {
+    public JavassistParameterDeclaration(ResolvedType type, TypeSolver typeSolver, boolean variadic, String name) {
+        this.name = name;
         this.type = type;
         this.typeSolver = typeSolver;
         this.variadic = variadic;
@@ -49,18 +51,23 @@
     }
 
     @Override
+    public boolean hasName() {
+        return name != null;
+    }
+
+    @Override
     public String getName() {
-        throw new UnsupportedOperationException();
+        return name;
     }
 
     @Override
     public boolean isField() {
-        throw new UnsupportedOperationException();
+        return false;
     }
 
     @Override
     public boolean isParameter() {
-        throw new UnsupportedOperationException();
+        return true;
     }
 
     @Override
@@ -70,7 +77,7 @@
 
     @Override
     public boolean isType() {
-        throw new UnsupportedOperationException();
+        return false;
     }
 
     @Override
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java
index ae56434..2a3cfa5 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java
@@ -18,6 +18,7 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import javassist.CtClass;
 import javassist.NotFoundException;
+import javassist.bytecode.AccessFlag;
 import javassist.bytecode.BadBytecode;
 import javassist.bytecode.SignatureAttribute;
 
@@ -39,11 +40,14 @@
 
   public Set<ResolvedMethodDeclaration> getDeclaredMethods() {
     return Arrays.stream(ctClass.getDeclaredMethods())
+        .filter(m -> ((m.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0)
+                  && ((m.getMethodInfo().getAccessFlags() & AccessFlag.SYNTHETIC) == 0))
         .map(m -> new JavassistMethodDeclaration(m, typeSolver)).collect(Collectors.toSet());
   }
 
   public List<ResolvedConstructorDeclaration> getConstructors() {
     return Arrays.stream(ctClass.getConstructors())
+        .filter(m -> (m.getMethodInfo().getAccessFlags() & AccessFlag.SYNTHETIC) == 0)
         .map(m -> new JavassistConstructorDeclaration(m, typeSolver)).collect(Collectors.toList());
   }
 
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java
index bd99217..bbff281 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java
@@ -95,11 +95,12 @@
     @Override
     public List<ResolvedTypeParameterDeclaration.Bound> getBounds() {
         List<Bound> bounds = new ArrayList<>();
-        if (wrapped.getClassBound() != null && !wrapped.getClassBound().toString().equals(Object.class.getCanonicalName())) {
-            throw new UnsupportedOperationException(wrapped.getClassBound().toString());
+        SignatureAttribute.ObjectType classBound = wrapped.getClassBound();
+        if (classBound != null) {
+            bounds.add(Bound.extendsBound(JavassistUtils.signatureTypeToType(classBound, typeSolver, getContainer())));
         }
         for (SignatureAttribute.ObjectType ot : wrapped.getInterfaceBound()) {
-            throw new UnsupportedOperationException(ot.toString());
+            bounds.add(Bound.extendsBound(JavassistUtils.signatureTypeToType(ot, typeSolver, getContainer())));
         }
         return bounds;
     }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java
index 5b3d68e..7fc1b4d 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java
@@ -22,15 +22,11 @@
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeParametrizable;
 import com.github.javaparser.resolution.types.*;
-import com.github.javaparser.symbolsolver.core.resolution.Context;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.model.typesystem.*;
-import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
-import javassist.CtClass;
-import javassist.CtMethod;
-import javassist.NotFoundException;
-import javassist.bytecode.BadBytecode;
-import javassist.bytecode.SignatureAttribute;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import javassist.*;
+import javassist.bytecode.*;
 
 import java.util.*;
 import java.util.stream.Collectors;
@@ -40,30 +36,24 @@
  */
 class JavassistUtils {
 
-    static Optional<MethodUsage> getMethodUsage(CtClass ctClass, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, Context invokationContext) {
-        // TODO avoid bridge and synthetic methods
+    static Optional<MethodUsage> getMethodUsage(CtClass ctClass, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
+                                                List<ResolvedTypeParameterDeclaration> typeParameters, List<ResolvedType> typeParameterValues) {
+        List<MethodUsage> methods = new ArrayList<>();
         for (CtMethod method : ctClass.getDeclaredMethods()) {
-            if (method.getName().equals(name)) {
-                // TODO check typeParametersValues
+            if (method.getName().equals(name)
+                    && ((method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0)
+                    && ((method.getMethodInfo().getAccessFlags() & AccessFlag.SYNTHETIC) == 0)) {
                 MethodUsage methodUsage = new MethodUsage(new JavassistMethodDeclaration(method, typeSolver));
-                if (argumentsTypes.size() < methodUsage.getNoParams()) {
-                    // this method cannot be a good candidate (except if variadic ?)
-                    continue;
+                for (int i = 0; i < typeParameters.size() && i < typeParameterValues.size(); i++) {
+                    ResolvedTypeParameterDeclaration tpToReplace = typeParameters.get(i);
+                    ResolvedType newValue = typeParameterValues.get(i);
+                    methodUsage = methodUsage.replaceTypeParameter(tpToReplace, newValue);
                 }
-                try {
-                    if (method.getGenericSignature() != null) {
-                        SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(method.getGenericSignature());
-                        List<ResolvedType> parametersOfReturnType = parseTypeParameters(methodSignature.getReturnType().toString(), typeSolver, invokationContext);
-                        ResolvedType newReturnType = methodUsage.returnType();
-                        // consume one parametersOfReturnType at the time
-                        if (newReturnType.isReferenceType() && parametersOfReturnType.size() > 0) {
-                            newReturnType = newReturnType.asReferenceType().transformTypeParameters(tp -> parametersOfReturnType.remove(0));
-                        }
-                        methodUsage = methodUsage.replaceReturnType(newReturnType);
-                    }
+                methods.add(methodUsage);
+
+                // no need to search for overloaded/inherited methods if the method has no parameters
+                if (argumentsTypes.isEmpty() && methodUsage.getNoParams() == 0) {
                     return Optional.of(methodUsage);
-                } catch (BadBytecode e) {
-                    throw new RuntimeException(e);
                 }
             }
         }
@@ -71,9 +61,9 @@
         try {
             CtClass superClass = ctClass.getSuperclass();
             if (superClass != null) {
-                Optional<MethodUsage> ref = new JavassistClassDeclaration(superClass, typeSolver).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, null);
+                Optional<MethodUsage> ref = JavassistUtils.getMethodUsage(superClass, name, argumentsTypes, typeSolver, typeParameters, typeParameterValues);
                 if (ref.isPresent()) {
-                    return ref;
+                    methods.add(ref.get());
                 }
             }
         } catch (NotFoundException e) {
@@ -82,69 +72,27 @@
 
         try {
             for (CtClass interfaze : ctClass.getInterfaces()) {
-                Optional<MethodUsage> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, null);
+                Optional<MethodUsage> ref = JavassistUtils.getMethodUsage(interfaze, name, argumentsTypes, typeSolver, typeParameters, typeParameterValues);
                 if (ref.isPresent()) {
-                    return ref;
+                    methods.add(ref.get());
                 }
             }
         } catch (NotFoundException e) {
             throw new RuntimeException(e);
         }
 
-        return Optional.empty();
-    }
-
-    private static List<ResolvedType> parseTypeParameters(String signature, TypeSolver typeSolver, Context invokationContext) {
-        String originalSignature = signature;
-        if (signature.contains("<")) {
-            signature = signature.substring(signature.indexOf('<') + 1);
-            if (!signature.endsWith(">")) {
-                throw new IllegalArgumentException();
-            }
-            signature = signature.substring(0, signature.length() - 1);
-            if (signature.contains(",")) {
-                throw new UnsupportedOperationException();
-            }
-            if (signature.startsWith("?")) {
-                // TODO: check bounds
-                List<ResolvedType> types = new ArrayList<>();
-                types.add(ResolvedWildcard.UNBOUNDED);
-                return types;
-            }
-            List<ResolvedType> typeParameters = parseTypeParameters(signature, typeSolver, invokationContext);
-            if (signature.contains("<")) {
-                signature = signature.substring(0, signature.indexOf('<'));
-            }
-            if (signature.contains(">")) {
-                throw new UnsupportedOperationException();
-            }
-
-            ResolvedType type = new SymbolSolver(typeSolver).solveTypeUsage(signature, invokationContext);
-
-            if (type.isReferenceType() && typeParameters.size() > 0) {
-                type = type.asReferenceType().transformTypeParameters(tp -> typeParameters.remove(0));
-            }
-            List<ResolvedType> types = new ArrayList<>();
-            types.add(type);
-            return types;
-        } else {
-            return Collections.emptyList();
-        }
+        return MethodResolutionLogic.findMostApplicableUsage(methods, name, argumentsTypes, typeSolver);
     }
 
     static ResolvedType signatureTypeToType(SignatureAttribute.Type signatureType, TypeSolver typeSolver, ResolvedTypeParametrizable typeParametrizable) {
         if (signatureType instanceof SignatureAttribute.ClassType) {
             SignatureAttribute.ClassType classType = (SignatureAttribute.ClassType) signatureType;
             List<ResolvedType> typeArguments = classType.getTypeArguments() == null ? Collections.emptyList() : Arrays.stream(classType.getTypeArguments()).map(ta -> typeArgumentToType(ta, typeSolver, typeParametrizable)).collect(Collectors.toList());
-            final String typeName =
-                    classType.getDeclaringClass() != null ?
-                            classType.getDeclaringClass().getName() + "." + classType.getName() :
-                            classType.getName();
             ResolvedReferenceTypeDeclaration typeDeclaration = typeSolver.solveType(
-                    removeTypeArguments(internalNameToCanonicalName(typeName)));
+                    removeTypeArguments(internalNameToCanonicalName(getTypeName(classType))));
             return new ReferenceTypeImpl(typeDeclaration, typeArguments, typeSolver);
         } else if (signatureType instanceof SignatureAttribute.TypeVariable) {
-            SignatureAttribute.TypeVariable typeVariableSignature = (SignatureAttribute.TypeVariable)signatureType;
+            SignatureAttribute.TypeVariable typeVariableSignature = (SignatureAttribute.TypeVariable) signatureType;
             Optional<ResolvedTypeParameterDeclaration> typeParameterDeclarationOpt = typeParametrizable.findTypeParameter(typeVariableSignature.getName());
             if (!typeParameterDeclarationOpt.isPresent()) {
                 throw new UnsolvedSymbolException("Unable to solve TypeVariable " + typeVariableSignature);
@@ -165,7 +113,12 @@
             throw new RuntimeException(signatureType.getClass().getCanonicalName());
         }
     }
-    
+
+    private static String getTypeName(SignatureAttribute.ClassType classType) {
+        SignatureAttribute.ClassType declaringClass = classType.getDeclaringClass();
+        return declaringClass == null ? classType.getName() : getTypeName(declaringClass) + "." + classType.getName();
+    }
+
     private static String removeTypeArguments(String typeName) {
         if (typeName.contains("<")) {
             return typeName.substring(0, typeName.indexOf('<'));
@@ -174,21 +127,26 @@
         }
     }
 
-    private static String internalNameToCanonicalName(String typeName) {
+    static String internalNameToCanonicalName(String typeName) {
         return typeName.replaceAll("\\$", ".");
     }
 
     private static ResolvedType objectTypeArgumentToType(SignatureAttribute.ObjectType typeArgument, TypeSolver typeSolver, ResolvedTypeParametrizable typeParametrizable) {
-        String typeName = typeArgument.jvmTypeName();
-        Optional<ResolvedType> type = getGenericParameterByName(typeName, typeParametrizable);
-        return type.orElseGet(() -> new ReferenceTypeImpl(
-            typeSolver.solveType(removeTypeArguments(internalNameToCanonicalName(typeName))),
-            typeSolver));
+        if (typeArgument instanceof SignatureAttribute.ClassType) {
+            return signatureTypeToType(typeArgument, typeSolver, typeParametrizable);
+        } else if (typeArgument instanceof SignatureAttribute.ArrayType) {
+            return signatureTypeToType(((SignatureAttribute.ArrayType) typeArgument).getComponentType(), typeSolver, typeParametrizable);
+        } else {
+            String typeName = typeArgument.jvmTypeName();
+            return getGenericParameterByName(typeName, typeParametrizable, typeSolver);
+        }
     }
 
-    private static Optional<ResolvedType> getGenericParameterByName(String typeName, ResolvedTypeParametrizable typeParametrizable) {
-        Optional<ResolvedTypeParameterDeclaration> tp = typeParametrizable.findTypeParameter(typeName);
-        return tp.map(ResolvedTypeVariable::new);
+    private static ResolvedType getGenericParameterByName(String typeName, ResolvedTypeParametrizable typeParametrizable, TypeSolver typeSolver) {
+        Optional<ResolvedType> type = typeParametrizable.findTypeParameter(typeName).map(ResolvedTypeVariable::new);
+        return type.orElseGet(() -> new ReferenceTypeImpl(
+                typeSolver.solveType(removeTypeArguments(internalNameToCanonicalName(typeName))),
+                typeSolver));
     }
 
     private static ResolvedType typeArgumentToType(SignatureAttribute.TypeArgument typeArgument, TypeSolver typeSolver, ResolvedTypeParametrizable typeParametrizable) {
@@ -206,4 +164,34 @@
             return objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable);
         }
     }
+
+    /**
+     * Returns the {@code paramNumber}th parameter of a method or constructor, if it is available.
+     * <p>
+     * The name is not available, if
+     * <ul>
+     * <li>the method is abstract, i.e. explicitly declared as abstract or it is a non-default interface method</li>
+     * <li>methods and constructors from jar files, which have been compiled without debug symbols</li>
+     * </ul>
+     * <p>
+     * The parameters are counted from 0, skipping the implicit {@code this} parameter of non-static methods.
+     *
+     * @param method the method to look into
+     * @param paramNumber the number of the parameter to look for
+     * @return the found parameter name or empty, if the name is not available
+     */
+    static Optional<String> extractParameterName(CtBehavior method, int paramNumber) {
+        MethodInfo methodInfo = method.getMethodInfo();
+        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
+        if (codeAttribute != null) {
+            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute
+                    .tag);
+            if (attr != null) {
+                int pos = Modifier.isStatic(method.getModifiers()) ? 0 : 1;
+                return Optional.ofNullable(attr.variableName(paramNumber + pos));
+            }
+        }
+        return Optional.empty();
+    }
+
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/LazyType.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/LazyType.java
index 44dbdec..11f05dc 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/LazyType.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/LazyType.java
@@ -2,7 +2,6 @@
 
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.*;
-import com.github.javaparser.resolution.types.ResolvedType;
 
 import java.util.Map;
 import java.util.function.Function;
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
index 927253e..d6cbb14 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
@@ -17,6 +17,7 @@
 package com.github.javaparser.symbolsolver.model.typesystem;
 
 import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
@@ -27,10 +28,10 @@
 import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap;
 import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration;
+import com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -106,7 +107,7 @@
             }
         }
         if (other instanceof LambdaArgumentTypePlaceholder) {
-            return this.getTypeDeclaration().hasAnnotation(FunctionalInterface.class.getCanonicalName());
+            return FunctionalInterfaceLogic.isFunctionalInterfaceType(this);
         } else if (other instanceof ReferenceTypeImpl) {
             ReferenceTypeImpl otherRef = (ReferenceTypeImpl) other;
             if (compareConsideringTypeParameters(otherRef)) {
@@ -204,8 +205,35 @@
         return ancestors;
     }
 
+    public List<ResolvedReferenceType> getDirectAncestors() {
+        // We need to go through the inheritance line and propagate the type parametes
+
+        List<ResolvedReferenceType> ancestors = typeDeclaration.getAncestors();
+
+        ancestors = ancestors.stream()
+                .map(a -> typeParametersMap().replaceAll(a).asReferenceType())
+                .collect(Collectors.toList());
+
+        // Avoid repetitions of Object
+        ancestors.removeIf(a -> a.getQualifiedName().equals(Object.class.getCanonicalName()));
+        boolean isClassWithSuperClassOrObject = this.getTypeDeclaration().isClass()
+                && (this.getTypeDeclaration().asClass().getSuperClass() == null ||
+                        !this.getTypeDeclaration().asClass().getSuperClass().getQualifiedName().equals(Object.class.getCanonicalName())
+                || this.getTypeDeclaration().asClass().getQualifiedName().equals(Object.class.getCanonicalName()));
+        if (!isClassWithSuperClassOrObject) {
+            ResolvedReferenceTypeDeclaration objectType = typeSolver.solveType(Object.class.getCanonicalName());
+            ResolvedReferenceType objectRef = create(objectType);
+            ancestors.add(objectRef);
+        }
+        return ancestors;
+    }
+
     public ResolvedReferenceType deriveTypeParameters(ResolvedTypeParametersMap typeParametersMap) {
         return create(typeDeclaration, typeParametersMap);
     }
 
+    @Override
+    public Set<ResolvedFieldDeclaration> getDeclaredFields() {
+        return new HashSet<>(getTypeDeclaration().getDeclaredFields());
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java
new file mode 100644
index 0000000..6a26921
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.resolution.declarations.*;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @author Malte Skoruppa
+ */
+public class ReflectionAnnotationDeclaration extends AbstractTypeDeclaration implements ResolvedAnnotationDeclaration {
+
+    ///
+    /// Fields
+    ///
+
+    private Class<?> clazz;
+    private TypeSolver typeSolver;
+    private ReflectionClassAdapter reflectionClassAdapter;
+
+    ///
+    /// Constructor
+    ///
+
+    public ReflectionAnnotationDeclaration(Class<?> clazz, TypeSolver typeSolver) {
+        if (!clazz.isAnnotation()) {
+            throw new IllegalArgumentException("The given type is not an annotation.");
+        }
+
+        this.clazz = clazz;
+        this.typeSolver = typeSolver;
+        this.reflectionClassAdapter = new ReflectionClassAdapter(clazz, typeSolver, this);
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    @Override
+    public String getPackageName() {
+        if (clazz.getPackage() != null) {
+            return clazz.getPackage().getName();
+        }
+        return "";
+    }
+
+    @Override
+    public String getClassName() {
+        String qualifiedName = getQualifiedName();
+        if(qualifiedName.contains(".")) {
+            return qualifiedName.substring(qualifiedName.lastIndexOf("."), qualifiedName.length());
+        } else {
+            return qualifiedName;
+        }
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return clazz.getCanonicalName();
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+               "clazz=" + clazz.getCanonicalName() +
+               '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof ReflectionAnnotationDeclaration)) return false;
+
+        ReflectionAnnotationDeclaration that = (ReflectionAnnotationDeclaration) o;
+
+        return clazz.getCanonicalName().equals(that.clazz.getCanonicalName());
+    }
+
+    @Override
+    public int hashCode() {
+        return clazz.getCanonicalName().hashCode();
+    }
+
+    @Override
+    public boolean isAssignableBy(ResolvedType type) {
+        // TODO #1836
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        return reflectionClassAdapter.hasDirectlyAnnotation(canonicalName);
+    }
+
+    @Override
+    public List<ResolvedFieldDeclaration> getAllFields() {
+        // TODO #1837
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<ResolvedMethodDeclaration> getDeclaredMethods() {
+        // TODO #1838
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName() {
+        return clazz.getSimpleName();
+    }
+
+    @Override
+    public Optional<ResolvedReferenceTypeDeclaration> containerType() {
+        // TODO #1841
+        throw new UnsupportedOperationException("containerType() is not supported for " + this.getClass().getCanonicalName());
+    }
+
+    /**
+     * Annotation declarations cannot have type parameters and hence this method always returns an empty list.
+     *
+     * @return An empty list.
+     */
+    @Override
+    public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
+        // Annotation declarations cannot have type parameters - i.e. we can always return an empty list.
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<ResolvedAnnotationMemberDeclaration> getAnnotationMembers() {
+        return Stream.of(clazz.getDeclaredMethods())
+                       .map(m -> new ReflectionAnnotationMemberDeclaration(m, typeSolver))
+                       .collect(Collectors.toList());
+    }
+
+    @Override
+    public Optional<AnnotationDeclaration> toAst() {
+        return Optional.empty();
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationMemberDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationMemberDeclaration.java
new file mode 100644
index 0000000..fd0f463
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationMemberDeclaration.java
@@ -0,0 +1,40 @@
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.resolution.declarations.ResolvedAnnotationMemberDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Malte Skoruppa
+ */
+public class ReflectionAnnotationMemberDeclaration implements ResolvedAnnotationMemberDeclaration {
+
+    private Method annotationMember;
+    private TypeSolver typeSolver;
+
+    public ReflectionAnnotationMemberDeclaration(Method annotationMember, TypeSolver typeSolver) {
+        this.annotationMember = annotationMember;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public Expression getDefaultValue() {
+        // TODO we should do this:
+        // return annotationMember.getDefaultValue();
+        // TODO ...but the interface wants us to return a JavaParser Expression node.
+        throw new UnsupportedOperationException("Obtaining the default value of a reflection annotation member is not supported yet.");
+    }
+
+    @Override
+    public ResolvedType getType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName() {
+        return annotationMember.getName();
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java
index 5be7bec..94bea85 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java
@@ -104,12 +104,12 @@
                 return true;
             }
         }
-        ReferenceTypeImpl superclass = getSuperClass();
-        if (superclass == null) {
-            return false;
-        } else {
-            return superclass.getTypeDeclaration().hasField(name);
+        for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) {
+            if (ancestor.getTypeDeclaration().hasField(name)) {
+                return true;
+            }
         }
+        return false;
     }
 
     public List<ResolvedFieldDeclaration> getAllFields() {
@@ -176,7 +176,8 @@
     }
 
     public List<ResolvedConstructorDeclaration> getConstructors() {
-        return Arrays.stream(clazz.getConstructors())
+        return Arrays.stream(clazz.getDeclaredConstructors())
+                .filter(m -> !m.isSynthetic())
                 .map(m -> new ReflectionConstructorDeclaration(m, typeSolver))
                 .collect(Collectors.toList());
     }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration.java
index a93353c..df434f3 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration.java
@@ -23,6 +23,7 @@
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
 import com.github.javaparser.symbolsolver.javaparsermodel.contexts.ContextHelper;
 import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
@@ -42,7 +43,7 @@
 /**
  * @author Federico Tomassetti
  */
-public class ReflectionClassDeclaration extends AbstractClassDeclaration {
+public class ReflectionClassDeclaration extends AbstractClassDeclaration implements MethodUsageResolutionCapability {
 
     ///
     /// Fields
@@ -87,7 +88,9 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
+        // we do not attempt to perform any symbol solving when analyzing ancestors in the reflection model, so we can
+        // simply ignore the boolean parameter here; an UnsolvedSymbolException cannot occur
         return reflectionClassAdapter.getAncestors();
     }
 
@@ -131,6 +134,7 @@
         return clazz.getCanonicalName();
     }
 
+    @Override
     @Deprecated
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
         List<ResolvedMethodDeclaration> methods = new ArrayList<>();
@@ -140,20 +144,32 @@
             if (method.isBridge() || method.isSynthetic()) continue;
             ResolvedMethodDeclaration methodDeclaration = new ReflectionMethodDeclaration(method, typeSolver);
             methods.add(methodDeclaration);
+
+            // no need to search for overloaded/inherited methods if the method has no parameters
+            if (argumentsTypes.isEmpty() && methodDeclaration.getNumberOfParams() == 0) {
+                return SymbolReference.solved(methodDeclaration);
+            }
         }
         if (getSuperClass() != null) {
             ResolvedClassDeclaration superClass = (ResolvedClassDeclaration) getSuperClass().getTypeDeclaration();
-            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(superClass, name, argumentsTypes, staticOnly, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(superClass, name, argumentsTypes, staticOnly);
             if (ref.isSolved()) {
                 methods.add(ref.getCorrespondingDeclaration());
             }
         }
         for (ResolvedReferenceType interfaceDeclaration : getInterfaces()) {
-            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(interfaceDeclaration.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(interfaceDeclaration.getTypeDeclaration(), name, argumentsTypes, staticOnly);
             if (ref.isSolved()) {
                 methods.add(ref.getCorrespondingDeclaration());
             }
         }
+        // When empty there is no sense in trying to find the most applicable.
+        // This is useful for debugging. Performance is not affected as 
+        // MethodResolutionLogic.findMostApplicable method returns very early 
+        // when methods is empty.
+        if (methods.isEmpty()) {
+            return SymbolReference.unsolved(ResolvedMethodDeclaration.class);
+        }
         return MethodResolutionLogic.findMostApplicable(methods, name, argumentsTypes, typeSolver);
     }
 
@@ -169,7 +185,7 @@
         return new ReferenceTypeImpl(this, typeSolver);
     }
 
-    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, Context invokationContext, List<ResolvedType> typeParameterValues) {
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes, Context invokationContext, List<ResolvedType> typeParameterValues) {
         List<MethodUsage> methods = new ArrayList<>();
         for (Method method : Arrays.stream(clazz.getDeclaredMethods()).filter((m) -> m.getName().equals(name)).sorted(new MethodComparator()).collect(Collectors.toList())) {
             if (method.isBridge() || method.isSynthetic()) continue;
@@ -181,16 +197,21 @@
                 methodUsage = methodUsage.replaceTypeParameter(tpToReplace, newValue);
             }
             methods.add(methodUsage);
+
+            // no need to search for overloaded/inherited methods if the method has no parameters
+            if (argumentsTypes.isEmpty() && methodUsage.getNoParams() == 0) {
+                return Optional.of(methodUsage);
+            }
         }
         if (getSuperClass() != null) {
             ResolvedClassDeclaration superClass = (ResolvedClassDeclaration) getSuperClass().getTypeDeclaration();
-            Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(superClass, name, argumentsTypes, typeSolver, invokationContext, typeParameterValues);
+            Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(superClass, name, argumentsTypes, invokationContext, typeParameterValues);
             if (ref.isPresent()) {
                 methods.add(ref.get());
             }
         }
         for (ResolvedReferenceType interfaceDeclaration : getInterfaces()) {
-            Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(interfaceDeclaration.getTypeDeclaration(), name, argumentsTypes, typeSolver, invokationContext, typeParameterValues);
+            Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(interfaceDeclaration.getTypeDeclaration(), name, argumentsTypes, invokationContext, typeParameterValues);
             if (ref.isPresent()) {
                 methods.add(ref.get());
             }
@@ -332,6 +353,11 @@
                 .collect(Collectors.toSet());
     }
 
+    @Override
+    public Optional<Node> toAst() {
+        return Optional.empty();
+    }
+
     ///
     /// Protected methods
     ///
@@ -340,5 +366,4 @@
     protected ResolvedReferenceType object() {
         return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
     }
-
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration.java
index beb0c43..1183749 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration.java
@@ -17,6 +17,7 @@
 package com.github.javaparser.symbolsolver.reflectionmodel;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration;
@@ -27,6 +28,7 @@
 import java.lang.reflect.Constructor;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
@@ -37,8 +39,7 @@
     private Constructor<?> constructor;
     private TypeSolver typeSolver;
 
-    public ReflectionConstructorDeclaration(Constructor<?> constructor,
-                                            TypeSolver typeSolver) {
+    public ReflectionConstructorDeclaration(Constructor<?> constructor, TypeSolver typeSolver) {
         this.constructor = constructor;
         this.typeSolver = typeSolver;
     }
@@ -62,12 +63,14 @@
         if (constructor.isVarArgs()) {
             variadic = i == (constructor.getParameterCount() - 1);
         }
-        return new ReflectionParameterDeclaration(constructor.getParameterTypes()[i], constructor.getGenericParameterTypes()[i], typeSolver, variadic);
+        return new ReflectionParameterDeclaration(constructor.getParameterTypes()[i],
+                constructor.getGenericParameterTypes()[i], typeSolver, variadic,
+                constructor.getParameters()[i].getName());
     }
 
     @Override
     public String getName() {
-        return constructor.getName();
+        return constructor.getDeclaringClass().getSimpleName();
     }
 
     @Override
@@ -92,4 +95,9 @@
         }
         return ReflectionFactory.typeUsageFor(this.constructor.getExceptionTypes()[index], typeSolver);
     }
+
+    @Override
+    public Optional<ConstructorDeclaration> toAst() {
+        return Optional.empty();
+    }
 }
\ No newline at end of file
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumConstantDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumConstantDeclaration.java
index 07799e8..2342304 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumConstantDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumConstantDeclaration.java
@@ -1,8 +1,10 @@
 package com.github.javaparser.symbolsolver.reflectionmodel;
 
 import com.github.javaparser.resolution.declarations.ResolvedEnumConstantDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 
 import java.lang.reflect.Field;
 
@@ -26,6 +28,8 @@
 
     @Override
     public ResolvedType getType() {
-        throw new UnsupportedOperationException();
+        Class<?> enumClass = enumConstant.getDeclaringClass();
+        ResolvedReferenceTypeDeclaration typeDeclaration = new ReflectionEnumDeclaration(enumClass, typeSolver);
+        return new ReferenceTypeImpl(typeDeclaration, typeSolver);
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java
index a0b4bc3..5fcd270 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java
@@ -20,20 +20,24 @@
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
 import com.github.javaparser.symbolsolver.logic.ConfilictingGenericTypesException;
 import com.github.javaparser.symbolsolver.logic.InferenceContext;
+import com.github.javaparser.symbolsolver.logic.MethodResolutionCapability;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 
+import java.lang.reflect.Field;
 import java.util.*;
 import java.util.stream.Collectors;
 
 /**
  * @author Federico Tomassetti
  */
-public class ReflectionEnumDeclaration extends AbstractTypeDeclaration implements ResolvedEnumDeclaration {
+public class ReflectionEnumDeclaration extends AbstractTypeDeclaration
+        implements ResolvedEnumDeclaration, MethodResolutionCapability, MethodUsageResolutionCapability {
 
   ///
   /// Fields
@@ -105,7 +109,9 @@
   }
 
   @Override
-  public List<ResolvedReferenceType> getAncestors() {
+  public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
+    // we do not attempt to perform any symbol solving when analyzing ancestors in the reflection model, so we can
+    // simply ignore the boolean parameter here; an UnsolvedSymbolException cannot occur
     return reflectionClassAdapter.getAncestors();
   }
 
@@ -154,12 +160,13 @@
     return reflectionClassAdapter.getTypeParameters();
   }
 
+  @Override
   public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes, boolean staticOnly) {
     return ReflectionMethodResolutionLogic.solveMethod(name, parameterTypes, staticOnly,
             typeSolver,this, clazz);
   }
 
-  public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> parameterTypes, TypeSolver typeSolver,
+  public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> parameterTypes,
                                                   Context invokationContext, List<ResolvedType> typeParameterValues) {
     Optional<MethodUsage> res = ReflectionMethodResolutionLogic.solveMethodAsUsage(name, parameterTypes, typeSolver, invokationContext,
             typeParameterValues, this, clazz);
@@ -194,8 +201,20 @@
   @Override
   public List<ResolvedEnumConstantDeclaration> getEnumConstants() {
       return Arrays.stream(clazz.getFields())
-              .filter(f -> f.isEnumConstant())
+              .filter(Field::isEnumConstant)
               .map(c -> new ReflectionEnumConstantDeclaration(c, typeSolver))
               .collect(Collectors.toList());
   }
+
+  @Override
+  public Set<ResolvedReferenceTypeDeclaration> internalTypes() {
+    return Arrays.stream(this.clazz.getDeclaredClasses())
+            .map(ic -> ReflectionFactory.typeDeclarationFor(ic, typeSolver))
+            .collect(Collectors.toSet());
+  }
+
+  @Override
+  public List<ResolvedConstructorDeclaration> getConstructors() {
+    return reflectionClassAdapter.getConstructors();
+  }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java
index fe0fc34..e095334 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java
@@ -19,9 +19,7 @@
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
-import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.*;
-import com.github.javaparser.resolution.types.ResolvedTypeVariable;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.*;
 
@@ -43,6 +41,8 @@
             throw new IllegalArgumentException("No type declaration available for an Array");
         } else if (clazz.isPrimitive()) {
             throw new IllegalArgumentException();
+        } else if (clazz.isAnnotation()) {
+            return new ReflectionAnnotationDeclaration(clazz, typeSolver);
         } else if (clazz.isInterface()) {
             return new ReflectionInterfaceDeclaration(clazz, typeSolver);
         } else if (clazz.isEnum()) {
@@ -115,7 +115,7 @@
         } else if (Modifier.isPrivate(modifiers)) {
             return AccessSpecifier.PRIVATE;
         } else {
-            return AccessSpecifier.DEFAULT;
+            return AccessSpecifier.PACKAGE_PRIVATE;
         }
     }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java
index 7453e23..50d944d 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java
@@ -18,15 +18,18 @@
 
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.MethodUsageResolutionCapability;
 import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
 import com.github.javaparser.symbolsolver.logic.ConfilictingGenericTypesException;
 import com.github.javaparser.symbolsolver.logic.InferenceContext;
+import com.github.javaparser.symbolsolver.logic.MethodResolutionCapability;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.NullType;
@@ -39,7 +42,8 @@
 /**
  * @author Federico Tomassetti
  */
-public class ReflectionInterfaceDeclaration extends AbstractTypeDeclaration implements ResolvedInterfaceDeclaration {
+public class ReflectionInterfaceDeclaration extends AbstractTypeDeclaration
+        implements ResolvedInterfaceDeclaration, MethodResolutionCapability, MethodUsageResolutionCapability {
 
     ///
     /// Fields
@@ -84,7 +88,7 @@
     public String getClassName() {
         String canonicalName = clazz.getCanonicalName();
         if (canonicalName != null && getPackageName() != null) {
-            return canonicalName.substring(getPackageName().length() + 1, canonicalName.length());
+            return canonicalName.substring(getPackageName().length() + 1);
         }
         return null;
     }
@@ -94,6 +98,7 @@
         return clazz.getCanonicalName();
     }
 
+    @Override
     @Deprecated
     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes, boolean staticOnly) {
         return ReflectionMethodResolutionLogic.solveMethod(name, parameterTypes, staticOnly,
@@ -132,7 +137,7 @@
         return clazz.hashCode();
     }
 
-    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> parameterTypes, TypeSolver typeSolver,
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> parameterTypes,
                                                     Context invokationContext, List<ResolvedType> typeParameterValues) {
         Optional<MethodUsage> res = ReflectionMethodResolutionLogic.solveMethodAsUsage(name, parameterTypes, typeSolver, invokationContext,
                 typeParameterValues, this, clazz);
@@ -240,7 +245,9 @@
     }
 
     @Override
-    public List<ResolvedReferenceType> getAncestors() {
+    public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
+        // we do not attempt to perform any symbol solving when analyzing ancestors in the reflection model, so we can
+        // simply ignore the boolean parameter here; an UnsolvedSymbolException cannot occur
         return reflectionClassAdapter.getAncestors();
     }
 
@@ -304,4 +311,14 @@
     public AccessSpecifier accessSpecifier() {
         return ReflectionFactory.modifiersToAccessLevel(this.clazz.getModifiers());
     }
+
+    @Override
+    public List<ResolvedConstructorDeclaration> getConstructors() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Optional<ClassOrInterfaceDeclaration> toAst() {
+        return Optional.empty();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java
index 04047c6..9708f04 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java
@@ -17,6 +17,7 @@
 package com.github.javaparser.symbolsolver.reflectionmodel;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration;
@@ -24,6 +25,7 @@
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.core.resolution.TypeVariableResolutionCapability;
 import com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
@@ -31,12 +33,13 @@
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 /**
  * @author Federico Tomassetti
  */
-public class ReflectionMethodDeclaration implements ResolvedMethodDeclaration {
+public class ReflectionMethodDeclaration implements ResolvedMethodDeclaration, TypeVariableResolutionCapability {
 
     private Method method;
     private TypeSolver typeSolver;
@@ -104,7 +107,8 @@
         if (method.isVarArgs()) {
             variadic = i == (method.getParameterCount() - 1);
         }
-        return new ReflectionParameterDeclaration(method.getParameterTypes()[i], method.getGenericParameterTypes()[i], typeSolver, variadic);
+        return new ReflectionParameterDeclaration(method.getParameterTypes()[i], method.getGenericParameterTypes()[i],
+                typeSolver, variadic, method.getParameters()[i].getName());
     }
 
     @Override
@@ -148,4 +152,9 @@
         }
         return ReflectionFactory.typeUsageFor(this.method.getExceptionTypes()[index], typeSolver);
     }
+
+    @Override
+    public Optional<MethodDeclaration> toAst() {
+        return Optional.empty();
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic.java
index acf39c2..bf4114c 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic.java
@@ -54,7 +54,7 @@
         }
 
         for (ResolvedReferenceType ancestor : scopeType.getAncestors()) {
-            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, parameterTypes, staticOnly, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, parameterTypes, staticOnly);
             if (ref.isSolved()) {
                 methods.add(ref.getCorrespondingDeclaration());
             }
@@ -62,7 +62,7 @@
 
         if (scopeType.getAncestors().isEmpty()){
             ReferenceTypeImpl objectClass = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
-            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(objectClass.getTypeDeclaration(), name, parameterTypes, staticOnly, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(objectClass.getTypeDeclaration(), name, parameterTypes, staticOnly);
             if (ref.isSolved()) {
                 methods.add(ref.getCorrespondingDeclaration());
             }
@@ -94,7 +94,7 @@
         }
 
         for(ResolvedReferenceType ancestor : scopeType.getAncestors()){
-            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes);
             if (ref.isSolved()){
                 ResolvedMethodDeclaration correspondingDeclaration = ref.getCorrespondingDeclaration();
                 MethodUsage methodUsage = replaceParams(typeParameterValues, ancestor.getTypeDeclaration(), correspondingDeclaration);
@@ -104,7 +104,7 @@
 
         if (scopeType.getAncestors().isEmpty()){
             ReferenceTypeImpl objectClass = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
-            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(objectClass.getTypeDeclaration(), name, argumentsTypes, typeSolver);
+            SymbolReference<ResolvedMethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(objectClass.getTypeDeclaration(), name, argumentsTypes);
             if (ref.isSolved()) {
                 MethodUsage usage = replaceParams(typeParameterValues, objectClass.getTypeDeclaration(), ref.getCorrespondingDeclaration());
                 methods.add(usage);
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration.java
index be5e9df..a96f9b6 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration.java
@@ -20,6 +20,8 @@
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
+import java.util.Objects;
+
 /**
  * @author Federico Tomassetti
  */
@@ -28,23 +30,44 @@
     private java.lang.reflect.Type genericType;
     private TypeSolver typeSolver;
     private boolean variadic;
+    private String name;
 
-    public ReflectionParameterDeclaration(Class<?> type, java.lang.reflect.Type genericType, TypeSolver typeSolver, boolean variadic) {
+    /**
+     *
+     * @param type
+     * @param genericType
+     * @param typeSolver
+     * @param variadic
+     * @param name can potentially be null
+     */
+    public ReflectionParameterDeclaration(Class<?> type, java.lang.reflect.Type genericType, TypeSolver typeSolver,
+                                          boolean variadic, String name) {
         this.type = type;
         this.genericType = genericType;
         this.typeSolver = typeSolver;
         this.variadic = variadic;
+        this.name = name;
+    }
+
+    /**
+     *
+     * @return the name, which can be potentially null
+     */
+    @Override
+    public String getName() {
+        return name;
     }
 
     @Override
-    public String getName() {
-        throw new UnsupportedOperationException();
+    public boolean hasName() {
+        return name != null;
     }
 
     @Override
     public String toString() {
         return "ReflectionParameterDeclaration{" +
                 "type=" + type +
+                ", name=" + name +
                 '}';
     }
 
@@ -72,4 +95,21 @@
     public ResolvedType getType() {
         return ReflectionFactory.typeUsageFor(genericType, typeSolver);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ReflectionParameterDeclaration that = (ReflectionParameterDeclaration) o;
+        return variadic == that.variadic &&
+                Objects.equals(type, that.type) &&
+                Objects.equals(genericType, that.genericType) &&
+                Objects.equals(typeSolver, that.typeSolver) &&
+                Objects.equals(name, that.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, genericType, typeSolver, variadic, name);
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic.java
index 01fdfaa..3c8d6de 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic.java
@@ -20,23 +20,15 @@
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.*;
-import com.github.javaparser.symbolsolver.core.resolution.Context;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration;
-import com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration;
-import com.github.javaparser.symbolsolver.javassistmodel.JavassistEnumDeclaration;
-import com.github.javaparser.symbolsolver.javassistmodel.JavassistInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.logic.MethodResolutionCapability;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.model.typesystem.*;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionEnumDeclaration;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
@@ -93,7 +85,7 @@
                 } // else it is already assignable, nothing to do
             } else {
                 if (pos > argumentsTypes.size()) {
-                  return false;
+                    return false;
                 }
                 argumentsTypes = groupVariadicParamValues(argumentsTypes, pos, method.getLastParam().getType());
             }
@@ -186,7 +178,7 @@
 
             // In the case of nested parameterizations eg. List<R> <-> List<Integer>
             // we should peel off one layer and ensure R <-> Integer
-            if (expectedParam.isReferenceType() && actualParam.isReferenceType()){
+            if (expectedParam.isReferenceType() && actualParam.isReferenceType()) {
                 ResolvedReferenceType r1 = expectedParam.asReferenceType();
                 ResolvedReferenceType r2 = actualParam.asReferenceType();
 
@@ -236,7 +228,7 @@
     }
 
     public static ResolvedType replaceTypeParam(ResolvedType type, ResolvedTypeParameterDeclaration tp, TypeSolver typeSolver) {
-        if (type.isTypeVariable()) {
+        if (type.isTypeVariable() || type.isWildcard()) {
             if (type.describe().equals(tp.getName())) {
                 List<ResolvedTypeParameterDeclaration.Bound> bounds = tp.getBounds();
                 if (bounds.size() > 1) {
@@ -256,18 +248,6 @@
             ResolvedReferenceType result = type.asReferenceType();
             result = result.transformTypeParameters(typeParam -> replaceTypeParam(typeParam, tp, typeSolver)).asReferenceType();
             return result;
-        } else if (type.isWildcard()) {
-            if (type.describe().equals(tp.getName())) {
-                List<ResolvedTypeParameterDeclaration.Bound> bounds = tp.getBounds();
-                if (bounds.size() > 1) {
-                    throw new UnsupportedOperationException();
-                } else if (bounds.size() == 1) {
-                    return bounds.get(0).getType();
-                } else {
-                    return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
-                }
-            }
-            return type;
         } else {
             throw new UnsupportedOperationException("Replacing " + type + ", param " + tp + " with " + type.getClass().getCanonicalName());
         }
@@ -290,7 +270,7 @@
             List<ResolvedTypeParameterDeclaration> typeParameters = method.getDeclaration().getTypeParameters();
             typeParameters.addAll(method.declaringType().getTypeParameters());
 
-            if (expectedType.describe().equals(actualType.describe())){
+            if (expectedType.describe().equals(actualType.describe())) {
                 return true;
             }
 
@@ -304,7 +284,7 @@
                 inferTypes(argumentsTypes.get(j), parameterType, derivedValues);
             }
 
-            for (Map.Entry<ResolvedTypeParameterDeclaration, ResolvedType> entry : derivedValues.entrySet()){
+            for (Map.Entry<ResolvedTypeParameterDeclaration, ResolvedType> entry : derivedValues.entrySet()) {
                 ResolvedTypeParameterDeclaration tp = entry.getKey();
                 expectedTypeWithInference = expectedTypeWithInference.replaceTypeVariables(tp, entry.getValue());
             }
@@ -350,34 +330,24 @@
         }
         return true;
     }
-
-    private static List<ResolvedMethodDeclaration> getMethodsWithoutDuplicates(List<ResolvedMethodDeclaration> methods) {
-        Set<ResolvedMethodDeclaration> s = new TreeSet<>((m1, m2) -> {
-            if (m1 instanceof JavaParserMethodDeclaration && m2 instanceof JavaParserMethodDeclaration &&
-                    ((JavaParserMethodDeclaration) m1).getWrappedNode().equals(((JavaParserMethodDeclaration) m2).getWrappedNode())) {
-                return 0;
-            }
-            return 1;
-        });
-        s.addAll(methods);
-        List<ResolvedMethodDeclaration> res = new ArrayList<>();
-        Set<String> usedSignatures = new HashSet<>();
-        for (ResolvedMethodDeclaration md : methods) {
-            String signature = md.getQualifiedSignature();
-            if (!usedSignatures.contains(signature)) {
-                usedSignatures.add(signature);
-                res.add(md);
-            }
-        }
-        return res;
+    
+    /**
+     * Filters by given function {@param keyExtractor} using a stateful filter mechanism.
+     * 
+     * <pre>
+     *      persons.stream().filter(distinctByKey(Person::getName))
+     * </pre>
+     * 
+     * The example above would return a distinct list of persons containing only one person per name.
+     * 
+     */
+    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
+        Set<Object> seen = ConcurrentHashMap.newKeySet();
+        return t -> seen.add(keyExtractor.apply(t));
     }
 
     /**
-     * @param methods        we expect the methods to be ordered such that inherited methods are later in the list
-     * @param name
-     * @param argumentsTypes
-     * @param typeSolver
-     * @return
+     * @param methods we expect the methods to be ordered such that inherited methods are later in the list
      */
     public static SymbolReference<ResolvedMethodDeclaration> findMostApplicable(List<ResolvedMethodDeclaration> methods,
                                                                                 String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
@@ -390,32 +360,43 @@
 
     public static SymbolReference<ResolvedMethodDeclaration> findMostApplicable(List<ResolvedMethodDeclaration> methods,
                                                                                 String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, boolean wildcardTolerance) {
-        List<ResolvedMethodDeclaration> applicableMethods = getMethodsWithoutDuplicates(methods).stream().filter((m) -> isApplicable(m, name, argumentsTypes, typeSolver, wildcardTolerance)).collect(Collectors.toList());
+        
+        List<ResolvedMethodDeclaration> methodsWithMatchingName = methods.stream()
+                .filter(m -> m.getName().equals(name))
+                .collect(Collectors.toList());
+        
+        List<ResolvedMethodDeclaration> applicableMethods = methodsWithMatchingName.stream()
+                // Filters out duplicate ResolvedMethodDeclaration by their signature.
+                .filter(distinctByKey(ResolvedMethodDeclaration::getQualifiedSignature)) 
+                // Checks if ResolvedMethodDeclaration is applicable to argumentsTypes.
+                .filter((m) -> isApplicable(m, name, argumentsTypes, typeSolver, wildcardTolerance))
+                .collect(Collectors.toList());
+        
         if (applicableMethods.isEmpty()) {
             return SymbolReference.unsolved(ResolvedMethodDeclaration.class);
         }
 
         if (applicableMethods.size() > 1) {
-          List<Integer> nullParamIndexes = new ArrayList<>();
-          for (int i = 0; i < argumentsTypes.size(); i++) {
-            if (argumentsTypes.get(i).isNull()) {
-              nullParamIndexes.add(i);
-            }
-          }
-          if (!nullParamIndexes.isEmpty()) {
-            // remove method with array param if a non array exists and arg is null
-            Set<ResolvedMethodDeclaration> removeCandidates = new HashSet<>();
-            for (Integer nullParamIndex: nullParamIndexes) {
-              for (ResolvedMethodDeclaration methDecl: applicableMethods) {
-                if (methDecl.getParam(nullParamIndex.intValue()).getType().isArray()) {
-                  removeCandidates.add(methDecl);
+            List<Integer> nullParamIndexes = new ArrayList<>();
+            for (int i = 0; i < argumentsTypes.size(); i++) {
+                if (argumentsTypes.get(i).isNull()) {
+                    nullParamIndexes.add(i);
                 }
-              }
             }
-            if (!removeCandidates.isEmpty() && removeCandidates.size() < applicableMethods.size()) {
-              applicableMethods.removeAll(removeCandidates);
+            if (!nullParamIndexes.isEmpty()) {
+                // remove method with array param if a non array exists and arg is null
+                Set<ResolvedMethodDeclaration> removeCandidates = new HashSet<>();
+                for (Integer nullParamIndex : nullParamIndexes) {
+                    for (ResolvedMethodDeclaration methDecl : applicableMethods) {
+                        if (methDecl.getParam(nullParamIndex).getType().isArray()) {
+                            removeCandidates.add(methDecl);
+                        }
+                    }
+                }
+                if (!removeCandidates.isEmpty() && removeCandidates.size() < applicableMethods.size()) {
+                    applicableMethods.removeAll(removeCandidates);
+                }
             }
-          }
         }
         if (applicableMethods.size() == 1) {
             return SymbolReference.solved(applicableMethods.get(0));
@@ -425,9 +406,9 @@
             boolean possibleAmbiguity = false;
             for (int i = 1; i < applicableMethods.size(); i++) {
                 other = applicableMethods.get(i);
-                if (isMoreSpecific(winningCandidate, other, argumentsTypes, typeSolver)) {
+                if (isMoreSpecific(winningCandidate, other, argumentsTypes)) {
                     possibleAmbiguity = false;
-                } else if (isMoreSpecific(other, winningCandidate, argumentsTypes, typeSolver)) {
+                } else if (isMoreSpecific(other, winningCandidate, argumentsTypes)) {
                     possibleAmbiguity = false;
                     winningCandidate = other;
                 } else {
@@ -439,80 +420,120 @@
                 }
             }
             if (possibleAmbiguity) {
-              // pick the first exact match if it exists
-              if (!isExactMatch(winningCandidate, argumentsTypes)) {
-                if (isExactMatch(other, argumentsTypes)) {
-                  winningCandidate = other;
-                } else {
-                  throw new MethodAmbiguityException("Ambiguous method call: cannot find a most applicable method: " + winningCandidate + ", " + other);
+                // pick the first exact match if it exists
+                if (!isExactMatch(winningCandidate, argumentsTypes)) {
+                    if (isExactMatch(other, argumentsTypes)) {
+                        winningCandidate = other;
+                    } else {
+                        throw new MethodAmbiguityException("Ambiguous method call: cannot find a most applicable method: " + winningCandidate + ", " + other);
+                    }
                 }
-              }
             }
             return SymbolReference.solved(winningCandidate);
         }
     }
 
     protected static boolean isExactMatch(ResolvedMethodLikeDeclaration method, List<ResolvedType> argumentsTypes) {
-      for (int i = 0; i < method.getNumberOfParams(); i++) {
-        if (!method.getParam(i).getType().equals(argumentsTypes.get(i))) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    private static boolean isMoreSpecific(ResolvedMethodDeclaration methodA, ResolvedMethodDeclaration methodB,
-                                          List<ResolvedType> argumentTypes, TypeSolver typeSolver) {
-        boolean oneMoreSpecificFound = false;
-        if (methodA.getNumberOfParams() < methodB.getNumberOfParams()) {
-            return true;
-        }
-        if (methodA.getNumberOfParams() > methodB.getNumberOfParams()) {
-            return false;
-        }
-        for (int i = 0; i < methodA.getNumberOfParams(); i++) {
-            ResolvedType tdA = methodA.getParam(i).getType();
-            ResolvedType tdB = methodB.getParam(i).getType();
-            // B is more specific
-            if (tdB.isAssignableBy(tdA) && !tdA.isAssignableBy(tdB)) {
-                oneMoreSpecificFound = true;
-            }
-            // A is more specific
-            if (tdA.isAssignableBy(tdB) && !tdB.isAssignableBy(tdA)) {
+        for (int i = 0; i < method.getNumberOfParams(); i++) {
+            if (!method.getParam(i).getType().equals(argumentsTypes.get(i))) {
                 return false;
             }
         }
+        return true;
+    }
 
-        if (!oneMoreSpecificFound) {
-            int lastIndex = argumentTypes.size() - 1;
+    private static ResolvedType getMethodsExplicitAndVariadicParameterType(ResolvedMethodDeclaration method, int i) {
+        int numberOfParams = method.getNumberOfParams();
 
-            if (methodA.hasVariadicParameter() && !methodB.hasVariadicParameter()) {
-                // if the last argument is an array then m1 is more specific
-                if (argumentTypes.get(lastIndex).isArray()) {
-                    return true;
-                }
+        if (i < numberOfParams) {
+            return method.getParam(i).getType();
+        } else if (method.hasVariadicParameter()) {
+            return method.getParam(numberOfParams - 1).getType();
+        } else {
+            return null;
+        }
+    }
 
-                if (!argumentTypes.get(lastIndex).isArray()) {
-                    return false;
-                }
+    private static boolean isMoreSpecific(ResolvedMethodDeclaration methodA, ResolvedMethodDeclaration methodB,
+                                          List<ResolvedType> argumentTypes) {
+
+        final boolean aVariadic = methodA.hasVariadicParameter();
+        final boolean bVariadic = methodB.hasVariadicParameter();
+        final int aNumberOfParams = methodA.getNumberOfParams();
+        final int bNumberOfParams = methodB.getNumberOfParams();
+        final int numberOfArgs = argumentTypes.size();
+        final ResolvedType lastArgType = numberOfArgs > 0 ? argumentTypes.get(numberOfArgs - 1) : null;
+        final boolean isLastArgArray = lastArgType != null && lastArgType.isArray();
+
+        // If one method declaration has exactly the correct amount of parameters and is not variadic then it is always
+        // preferred to a declaration that is variadic (and hence possibly also has a different amount of parameters).
+        if (!aVariadic && aNumberOfParams == numberOfArgs && (bVariadic && (bNumberOfParams != numberOfArgs ||
+                                                                            !isLastArgArray))) {
+            return true;
+        } else if (!bVariadic && bNumberOfParams == numberOfArgs && (aVariadic && (aNumberOfParams != numberOfArgs ||
+                                                                                   !isLastArgArray))) {
+            return false;
+        }
+
+        // Either both methods are variadic or neither is. So we must compare the parameter types.
+        for (int i = 0 ; i < numberOfArgs ; i++) {
+            ResolvedType paramTypeA = getMethodsExplicitAndVariadicParameterType(methodA, i);
+            ResolvedType paramTypeB = getMethodsExplicitAndVariadicParameterType(methodB, i);
+            ResolvedType argType = argumentTypes.get(i);
+
+            // Safety: if a type is null it means a signature with too few parameters managed to get to this point.
+            // This should not happen but it also means that this signature is immediately disqualified.
+            if (paramTypeA == null) {
+                return false;
+            } else if (paramTypeB == null) {
+                return true;
             }
-            if (!methodA.hasVariadicParameter() && methodB.hasVariadicParameter()) {
-                // if the last argument is an array and m1 is not variadic then
-                // it is not more specific
-                if (argumentTypes.get(lastIndex).isArray()) {
-                    return false;
-                }
+            // Widening primitive conversions have priority over boxing/unboxing conversions when finding the most
+            // applicable method. E.g. assume we have method call foo(1) and declarations foo(long) and foo(Integer).
+            // The method call will call foo(long), as it requires a widening primitive conversion from int to long
+            // instead of a boxing conversion from int to Integer. See JLS §15.12.2.
+            // This is what we check here.
+            else if (paramTypeA.isPrimitive() == argType.isPrimitive() &&
+                     paramTypeB.isPrimitive() != argType.isPrimitive() &&
+                     paramTypeA.isAssignableBy(argType)) {
 
-                if (!argumentTypes.get(lastIndex).isArray()) {
+                return true;
+            } else if (paramTypeB.isPrimitive() == argType.isPrimitive() &&
+                       paramTypeA.isPrimitive() != argType.isPrimitive() &&
+                       paramTypeB.isAssignableBy(argType)) {
+
+                return false;
+            }
+            // If we get to this point then we check whether one of the methods contains a parameter type that is more
+            // specific. If it does, we can assume the entire declaration is more specific as we would otherwise have
+            // a situation where the declarations are ambiguous in the given context.
+            else {
+                boolean aAssignableFromB = paramTypeA.isAssignableBy(paramTypeB);
+                boolean bAssignableFromA = paramTypeB.isAssignableBy(paramTypeA);
+
+                if (bAssignableFromA && !aAssignableFromB){
+                    // A's parameter is more specific
                     return true;
+                } else if (aAssignableFromB && !bAssignableFromA) {
+                    // B's parameter is more specific
+                    return false;
                 }
             }
         }
 
-        return oneMoreSpecificFound;
+        if (aVariadic && !bVariadic) {
+            // if the last argument is an array then m1 is more specific
+            return isLastArgArray;
+        } else if (!aVariadic && bVariadic) {
+            // if the last argument is an array and m1 is not variadic then
+            // it is not more specific
+            return !isLastArgArray;
+        }
+
+        return false;
     }
 
-    private static boolean isMoreSpecific(MethodUsage methodA, MethodUsage methodB, TypeSolver typeSolver) {
+    private static boolean isMoreSpecific(MethodUsage methodA, MethodUsage methodB) {
         boolean oneMoreSpecificFound = false;
         for (int i = 0; i < methodA.getNoParams(); i++) {
             ResolvedType tdA = methodA.getParamType(i);
@@ -545,9 +566,9 @@
             MethodUsage winningCandidate = applicableMethods.get(0);
             for (int i = 1; i < applicableMethods.size(); i++) {
                 MethodUsage other = applicableMethods.get(i);
-                if (isMoreSpecific(winningCandidate, other, typeSolver)) {
+                if (isMoreSpecific(winningCandidate, other)) {
                     // nothing to do
-                } else if (isMoreSpecific(other, winningCandidate, typeSolver)) {
+                } else if (isMoreSpecific(other, winningCandidate)) {
                     winningCandidate = other;
                 } else {
                     if (winningCandidate.declaringType().getQualifiedName().equals(other.declaringType().getQualifiedName())) {
@@ -580,65 +601,26 @@
     }
 
     public static SymbolReference<ResolvedMethodDeclaration> solveMethodInType(ResolvedTypeDeclaration typeDeclaration,
-                                                                               String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) {
-        return solveMethodInType(typeDeclaration, name, argumentsTypes, false, typeSolver);
+                                                                               String name,
+                                                                               List<ResolvedType> argumentsTypes) {
+        return solveMethodInType(typeDeclaration, name, argumentsTypes, false);
     }
 
-        /**
-         * Replace TypeDeclaration.solveMethod
-         *
-         * @param typeDeclaration
-         * @param name
-         * @param argumentsTypes
-         * @param staticOnly
-         * @return
-         */
+    // TODO: Replace TypeDeclaration.solveMethod
     public static SymbolReference<ResolvedMethodDeclaration> solveMethodInType(ResolvedTypeDeclaration typeDeclaration,
-                                                                               String name, List<ResolvedType> argumentsTypes, boolean staticOnly,
-                                                                               TypeSolver typeSolver) {
-        if (typeDeclaration instanceof JavaParserClassDeclaration) {
-            Context ctx = ((JavaParserClassDeclaration) typeDeclaration).getContext();
-            return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+                                                                               String name,
+                                                                               List<ResolvedType> argumentsTypes,
+                                                                               boolean staticOnly) {
+
+        if (typeDeclaration instanceof MethodResolutionCapability) {
+            return ((MethodResolutionCapability) typeDeclaration).solveMethod(name, argumentsTypes,
+                                                                              staticOnly);
+        } else {
+            throw new UnsupportedOperationException(typeDeclaration.getClass().getCanonicalName());
         }
-        if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
-            Context ctx = ((JavaParserInterfaceDeclaration) typeDeclaration).getContext();
-            return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
-        }
-        if (typeDeclaration instanceof JavaParserEnumDeclaration) {
-            if (name.equals("values") && argumentsTypes.isEmpty()) {
-                return SymbolReference.solved(new JavaParserEnumDeclaration.ValuesMethod((JavaParserEnumDeclaration) typeDeclaration, typeSolver));
-            }
-            Context ctx = ((JavaParserEnumDeclaration) typeDeclaration).getContext();
-            return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
-        }
-        if (typeDeclaration instanceof JavaParserAnonymousClassDeclaration) {
-        	Context ctx = ((JavaParserAnonymousClassDeclaration) typeDeclaration).getContext();
-            return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
-        }
-        if (typeDeclaration instanceof ReflectionClassDeclaration) {
-            return ((ReflectionClassDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
-        }
-        if (typeDeclaration instanceof ReflectionInterfaceDeclaration) {
-          return ((ReflectionInterfaceDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
-        }
-          if (typeDeclaration instanceof ReflectionEnumDeclaration) {
-            return ((ReflectionEnumDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
-        }
-        if (typeDeclaration instanceof JavassistInterfaceDeclaration) {
-            return ((JavassistInterfaceDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
-        }
-        if (typeDeclaration instanceof JavassistClassDeclaration) {
-          return ((JavassistClassDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
-        }
-          if (typeDeclaration instanceof JavassistEnumDeclaration) {
-            return ((JavassistEnumDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
-        }
-        throw new UnsupportedOperationException(typeDeclaration.getClass().getCanonicalName());
     }
 
     private static void inferTypes(ResolvedType source, ResolvedType target, Map<ResolvedTypeParameterDeclaration, ResolvedType> mappings) {
-
-
         if (source.equals(target)) {
             return;
         }
@@ -669,8 +651,8 @@
             return;
         }
 
-        if (source.isWildcard() && target.isReferenceType()){
-            if (source.asWildcard().isBounded()){
+        if (source.isWildcard() && target.isReferenceType()) {
+            if (source.asWildcard().isBounded()) {
                 inferTypes(source.asWildcard().getBoundedType(), target, mappings);
             }
             return;
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java
index ee4a735..b8f9160 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java
@@ -57,7 +57,7 @@
     }
 
     public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, Context context) {
-        return context.solveSymbol(name, typeSolver);
+        return context.solveSymbol(name);
     }
 
     public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, Node node) {
@@ -65,7 +65,7 @@
     }
 
     public Optional<Value> solveSymbolAsValue(String name, Context context) {
-        return context.solveSymbolAsValue(name, typeSolver);
+        return context.solveSymbolAsValue(name);
     }
 
     public Optional<Value> solveSymbolAsValue(String name, Node node) {
@@ -74,7 +74,7 @@
     }
 
     public SymbolReference<? extends ResolvedTypeDeclaration> solveType(String name, Context context) {
-        return context.solveType(name, typeSolver);
+        return context.solveType(name);
     }
 
     public SymbolReference<? extends ResolvedTypeDeclaration> solveType(String name, Node node) {
@@ -82,7 +82,7 @@
     }
 
     public MethodUsage solveMethod(String methodName, List<ResolvedType> argumentsTypes, Context context) {
-        SymbolReference<ResolvedMethodDeclaration> decl = context.solveMethod(methodName, argumentsTypes, false, typeSolver);
+        SymbolReference<ResolvedMethodDeclaration> decl = context.solveMethod(methodName, argumentsTypes, false);
         if (!decl.isSolved()) {
             throw new UnsolvedSymbolException(context.toString(), methodName);
         }
@@ -99,7 +99,7 @@
             // FIXME should call typesolver here!
 
             String name = ((ClassOrInterfaceType) type).getName().getId();
-            SymbolReference<ResolvedTypeDeclaration> ref = JavaParserFactory.getContext(type, typeSolver).solveType(name, typeSolver);
+            SymbolReference<ResolvedTypeDeclaration> ref = JavaParserFactory.getContext(type, typeSolver).solveType(name);
             if (!ref.isSolved()) {
                 throw new UnsolvedSymbolException(JavaParserFactory.getContext(type, typeSolver).toString(), name);
             }
@@ -110,7 +110,7 @@
     }
 
     public ResolvedType solveTypeUsage(String name, Context context) {
-        Optional<ResolvedType> genericType = context.solveGenericType(name, typeSolver);
+        Optional<ResolvedType> genericType = context.solveGenericType(name);
         if (genericType.isPresent()) {
             return genericType.get();
         }
@@ -127,15 +127,15 @@
     public SymbolReference<? extends ResolvedValueDeclaration> solveSymbolInType(ResolvedTypeDeclaration typeDeclaration, String name) {
         if (typeDeclaration instanceof JavaParserClassDeclaration) {
             Context ctx = ((JavaParserClassDeclaration) typeDeclaration).getContext();
-            return ctx.solveSymbol(name, typeSolver);
+            return ctx.solveSymbol(name);
         }
         if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
             Context ctx = ((JavaParserInterfaceDeclaration) typeDeclaration).getContext();
-            return ctx.solveSymbol(name, typeSolver);
+            return ctx.solveSymbol(name);
         }
         if (typeDeclaration instanceof JavaParserEnumDeclaration) {
             Context ctx = ((JavaParserEnumDeclaration) typeDeclaration).getContext();
-            return ctx.solveSymbol(name, typeSolver);
+            return ctx.solveSymbol(name);
         }
         if (typeDeclaration instanceof ReflectionClassDeclaration) {
             return ((ReflectionClassDeclaration) typeDeclaration).solveSymbol(name, typeSolver);
@@ -157,14 +157,17 @@
 
     /**
      * Try to solve a symbol just in the declaration, it does not delegate to the container.
+     *
+     * @deprecated Similarly to solveType this should eventually disappear as the symbol resolution logic should be more general
+     * and do not be specific to JavaParser classes like in this case.
      */
     @Deprecated
     public SymbolReference<ResolvedTypeDeclaration> solveTypeInType(ResolvedTypeDeclaration typeDeclaration, String name) {
         if (typeDeclaration instanceof JavaParserClassDeclaration) {
-            return ((JavaParserClassDeclaration) typeDeclaration).solveType(name, typeSolver);
+            return ((JavaParserClassDeclaration) typeDeclaration).solveType(name);
         }
         if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
-            return ((JavaParserInterfaceDeclaration) typeDeclaration).solveType(name, typeSolver);
+            return ((JavaParserInterfaceDeclaration) typeDeclaration).solveType(name);
         }
         return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
     }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameCategory.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameCategory.java
new file mode 100644
index 0000000..2847d40
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameCategory.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016-2018 The JavaParser Team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.naming;
+
+/**
+ * Context causes a name syntactically to fall into one of seven categories: ModuleName, PackageName, TypeName,
+ * ExpressionName, MethodName, PackageOrTypeName, or AmbiguousName.
+ * TypeName is less expressive than the other six categories, because it is denoted with TypeIdentifier, which excludes
+ * the character sequence var (§3.8).
+ *
+ * See JLS 6.5 (https://docs.oracle.com/javase/specs/jls/se10/html/jls-6.html#jls-6.5)
+ */
+public enum NameCategory {
+    MODULE_NAME(false),
+    PACKAGE_NAME(false),
+    TYPE_NAME(false),
+    EXPRESSION_NAME(false),
+    METHOD_NAME(false),
+    PACKAGE_OR_TYPE_NAME(true),
+    AMBIGUOUS_NAME(true),
+    COMPILATION_ERROR(false);
+
+    private boolean needDisambiguation;
+
+    NameCategory(boolean needDisambiguation) {
+        this.needDisambiguation = needDisambiguation;
+    }
+
+    /**
+     * Certain category include two or more unambiguous categories.
+     * These ambiguous categories are recognized solely through a syntactic process. In order to disambiguate them
+     * a semantic process (i.e., consider the symbols which are actually visible in a given context) is needed.
+     */
+    public boolean isNeedingDisambiguation() {
+        return needDisambiguation;
+    }
+
+    /**
+     * Is the given name acceptable for the given category?
+     */
+    public boolean isNameAcceptable(String name) {
+        return this != TYPE_NAME || !name.equals("var");
+    }
+
+    public boolean isValid() {
+        return this != COMPILATION_ERROR;
+    }
+
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogic.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogic.java
new file mode 100644
index 0000000..e6701b9
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogic.java
@@ -0,0 +1,996 @@
+package com.github.javaparser.symbolsolver.resolution.naming;
+
+import com.github.javaparser.ast.ImportDeclaration;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.modules.*;
+import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
+
+import com.github.javaparser.ast.stmt.TryStmt;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+
+/**
+ * NameLogic contains a set of static methods to implement the abstraction of a "Name" as defined
+ * in Chapter 6 of the JLS. This code could be moved to an interface or base class in a successive version of
+ * JavaParser.
+ */
+public class NameLogic {
+
+    /**
+     * Is the given node a non-qualified name?
+     *
+     * @throws IllegalArgumentException if the node is not a name
+     */
+    public static boolean isSimpleName(Node node) {
+        return !isQualifiedName(node);
+    }
+
+    /**
+     * Is the given node a qualified name?
+     *
+     * @throws IllegalArgumentException if the node is not a name
+     */
+    public static boolean isQualifiedName(Node node) {
+        if (!isAName(node)) {
+            throw new IllegalArgumentException();
+        }
+        return nameAsString(node).contains(".");
+    }
+
+    /**
+     * Does the Node represent a Name?
+     * <p>
+     * Note that while most specific AST classes either always represent names or never represent names
+     * there are exceptions as the FieldAccessExpr
+     */
+    public static boolean isAName(Node node) {
+        if (node instanceof FieldAccessExpr) {
+            FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) node;
+            return isAName(fieldAccessExpr.getScope());
+        } else {
+            return node instanceof SimpleName ||
+                    node instanceof Name ||
+                    node instanceof ClassOrInterfaceType ||
+                    node instanceof NameExpr;
+        }
+    }
+
+    private static Node getQualifier(Node node) {
+        if (node instanceof FieldAccessExpr) {
+            FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) node;
+            return fieldAccessExpr.getScope();
+        }
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    private static Node getRightMostName(Node node) {
+        if (node instanceof FieldAccessExpr) {
+            FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) node;
+            return fieldAccessExpr.getName();
+        }
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    /**
+     * What is the Role of the given name? Does it represent a Declaration or a Reference?
+     * <p>
+     * This classification is purely syntactical, i.e., it does not require symbol resolution. For this reason in the
+     * future this could be moved to the core module of JavaParser.
+     */
+    public static NameRole classifyRole(Node name) {
+        if (!isAName(name)) {
+            throw new IllegalArgumentException("The given node is not a name");
+        }
+        if (!name.getParentNode().isPresent()) {
+            throw new IllegalArgumentException("We cannot understand the role of a name if it has no parent");
+        }
+        if (whenParentIs(Name.class, name, (p, c) -> p.getQualifier().isPresent() && p.getQualifier().get() == c)) {
+            return classifyRole(name.getParentNode().get());
+        }
+        if (whenParentIs(PackageDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(ImportDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(MarkerAnnotationExpr.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ClassOrInterfaceDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(ClassOrInterfaceDeclaration.class, name, (p, c) -> p.getExtendedTypes().contains(c)
+                || p.getImplementedTypes().contains(c))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ClassOrInterfaceType.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(VariableDeclarator.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(NameExpr.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(FieldAccessExpr.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(MethodDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(Parameter.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(MethodCallExpr.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ConstructorDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(AnnotationDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(AnnotationMemberDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(AnnotationMemberDeclaration.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(MethodDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(MethodDeclaration.class, name, (p, c) -> p.getType() == c || p.getThrownExceptions().contains(c))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(Parameter.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(Parameter.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ReceiverParameter.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(MethodCallExpr.class, name, (p, c) -> p.getName() == c ||
+                (p.getTypeArguments().isPresent() && p.getTypeArguments().get().contains(c)) ||
+                (p.getScope().isPresent() && p.getScope().get() == c))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ConstructorDeclaration.class, name, (p, c) -> p.getName() == c || p.getThrownExceptions().contains(c))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(TypeParameter.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(EnumDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(EnumConstantDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(FieldAccessExpr.class, name, (p, c) -> p.getName() == c || p.getScope() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ObjectCreationExpr.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ReturnStmt.class, name, (p, c) -> p.getExpression().isPresent() && p.getExpression().get() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ModuleDeclaration.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(ModuleRequiresDirective.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ModuleExportsDirective.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ModuleExportsDirective.class, name, (p, c) -> p.getModuleNames().contains(c))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ModuleOpensDirective.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ModuleOpensDirective.class, name, (p, c) -> p.getModuleNames().contains(c))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ModuleUsesDirective.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ModuleProvidesDirective.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ClassExpr.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ThisExpr.class, name, (p, c) -> p.getTypeName().isPresent() && p.getTypeName().get() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(SuperExpr.class, name, (p, c) -> p.getTypeName().isPresent() && p.getTypeName().get() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(VariableDeclarator.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(VariableDeclarator.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ArrayCreationExpr.class, name, (p, c) -> p.getElementType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(CastExpr.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(InstanceOfExpr.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(TypeExpr.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ArrayAccessExpr.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(UnaryExpr.class, name, (p, c) -> p.getExpression() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(AssignExpr.class, name, (p, c) -> p.getTarget() == c || p.getValue() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(TryStmt.class, name, (p, c) -> p.getResources().contains(c))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(VariableDeclarator.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(VariableDeclarator.class, name, (p, c) -> p.getType() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(VariableDeclarator.class, name, (p, c) -> p.getInitializer().isPresent() && p.getInitializer().get() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(MemberValuePair.class, name, (p, c) -> p.getValue() == c)) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(MemberValuePair.class, name, (p, c) -> p.getName() == c)) {
+            return NameRole.DECLARATION;
+        }
+        if (whenParentIs(ExplicitConstructorInvocationStmt.class, name, (p, c) ->
+                (p.getExpression().isPresent() && p.getExpression().get() == c) ||
+                        (p.getTypeArguments().isPresent() && p.getTypeArguments().get().contains(c)))) {
+            return NameRole.REFERENCE;
+        }
+        if (whenParentIs(ObjectCreationExpr.class, name, (p, c) -> p.getType() == c ||
+                (p.getScope().isPresent() && p.getScope().get() == c))) {
+            return NameRole.REFERENCE;
+        }
+        if (name.getParentNode().isPresent() && NameLogic.isAName(name.getParentNode().get())) {
+            return classifyRole(name.getParentNode().get());
+        }
+        throw new UnsupportedOperationException("Unable to classify role of name contained in " + name.getParentNode().get().getClass().getSimpleName());
+    }
+
+    public static NameCategory classifyReference(Node name, TypeSolver typeSolver) {
+        if (!name.getParentNode().isPresent()) {
+            throw new IllegalArgumentException("We cannot understand the category of a name if it has no parent");
+        }
+        if (classifyRole(name) != NameRole.REFERENCE) {
+            throw new IllegalArgumentException("This method can be used only to classify names used as references");
+        }
+
+        // JLS 6.5
+        // First, context causes a name syntactically to fall into one of seven categories: ModuleName, PackageName,
+        // TypeName, ExpressionName, MethodName, PackageOrTypeName, or AmbiguousName.
+
+        NameCategory first = syntacticClassificationAccordingToContext(name);
+
+        // Second, a name that is initially classified by its context as an AmbiguousName or as a PackageOrTypeName is
+        // then reclassified to be a PackageName, TypeName, or ExpressionName.
+        if (first.isNeedingDisambiguation()) {
+            NameCategory second = reclassificationOfContextuallyAmbiguousNames(name, first, typeSolver);
+            assert !second.isNeedingDisambiguation();
+            return second;
+        } else {
+            return first;
+        }
+    }
+
+    /**
+     * JLS 6.5.2. Reclassification of Contextually Ambiguous Names
+     */
+    private static NameCategory reclassificationOfContextuallyAmbiguousNames(Node name, NameCategory ambiguousCategory,
+                                                                             TypeSolver typeSolver) {
+        if (!ambiguousCategory.isNeedingDisambiguation()) {
+            throw new IllegalArgumentException("The Name Category is not ambiguous: " + ambiguousCategory);
+        }
+        if (ambiguousCategory == NameCategory.AMBIGUOUS_NAME && isSimpleName(name)) {
+            return reclassificationOfContextuallyAmbiguousSimpleAmbiguousName(name, typeSolver);
+        }
+        if (ambiguousCategory == NameCategory.AMBIGUOUS_NAME && isQualifiedName(name)) {
+            return reclassificationOfContextuallyAmbiguousQualifiedAmbiguousName(name, typeSolver);
+        }
+        if (ambiguousCategory == NameCategory.PACKAGE_OR_TYPE_NAME) {
+            return reclassificationOfContextuallyAmbiguosPackageOrTypeName(name, typeSolver);
+        }
+        throw new UnsupportedOperationException("I do not know how to handle this semantic reclassification of ambiguous name categories");
+    }
+
+    private static NameCategory reclassificationOfContextuallyAmbiguosPackageOrTypeName(Node name, TypeSolver typeSolver) {
+        // 6.5.4.1. Simple PackageOrTypeNames
+        //
+        // If the PackageOrTypeName, Q, is a valid TypeIdentifier and occurs in the scope of a type named Q, then the
+        // PackageOrTypeName is reclassified as a TypeName.
+        //
+        // Otherwise, the PackageOrTypeName is reclassified as a PackageName. The meaning of the PackageOrTypeName is
+        // the meaning of the reclassified name.
+
+        if (isSimpleName(name)) {
+            if (JavaParserFactory.getContext(name, typeSolver).solveType(nameAsString(name)).isSolved()) {
+                return NameCategory.TYPE_NAME;
+            } else {
+                return NameCategory.PACKAGE_NAME;
+            }
+        }
+
+        // 6.5.4.2. Qualified PackageOrTypeNames
+        //
+        // Given a qualified PackageOrTypeName of the form Q.Id, if Id is a valid TypeIdentifier and the type or package
+        // denoted by Q has a member type named Id, then the qualified PackageOrTypeName name is reclassified as a
+        // TypeName.
+        //
+        // Otherwise, it is reclassified as a PackageName. The meaning of the qualified PackageOrTypeName is the meaning
+        // of the reclassified name.
+
+        if (isQualifiedName(name)) {
+            if (JavaParserFactory.getContext(name, typeSolver).solveType(nameAsString(name)).isSolved()) {
+                return NameCategory.TYPE_NAME;
+            } else {
+                return NameCategory.PACKAGE_NAME;
+            }
+        }
+
+        throw new UnsupportedOperationException("This is unexpected: the name is neither simple or qualified");
+    }
+
+    private static NameCategory reclassificationOfContextuallyAmbiguousQualifiedAmbiguousName(Node nameNode,
+                                                                                              TypeSolver typeSolver) {
+        // If the AmbiguousName is a qualified name, consisting of a name, a ".", and an Identifier, then the name to
+        // the left of the "." is first reclassified, for it is itself an AmbiguousName. There is then a choice:
+
+        Node leftName = NameLogic.getQualifier(nameNode);
+        String rightName = NameLogic.nameAsString(NameLogic.getRightMostName(nameNode));
+        NameCategory leftNameCategory = classifyReference(leftName, typeSolver);
+
+        // * If the name to the left of the "." is reclassified as a PackageName, then:
+        //
+        //      * If the Identifier is a valid TypeIdentifier, and there is a package whose name is the name to the left
+        //        of the ".", and that package contains a declaration of a type whose name is the same as the Identifier,
+        //        then this AmbiguousName is reclassified as a TypeName.
+        //
+        //      * Otherwise, this AmbiguousName is reclassified as a PackageName. A later step determines whether or not
+        //        a package of that name actually exists.
+
+        if (leftNameCategory == NameCategory.PACKAGE_NAME) {
+            if (typeSolver.hasType(nameAsString(nameNode))) {
+                return NameCategory.TYPE_NAME;
+            } else {
+                return NameCategory.PACKAGE_NAME;
+            }
+        }
+
+        // * If the name to the left of the "." is reclassified as a TypeName, then:
+        //
+        //      * If the Identifier is the name of a method or field of the type denoted by TypeName, then this
+        //        AmbiguousName is reclassified as an ExpressionName.
+        //
+        //      * Otherwise, if the Identifier is a valid TypeIdentifier and is the name of a member type of the type
+        //        denoted by TypeName, then this AmbiguousName is reclassified as a TypeName.
+        //
+        //      * Otherwise, a compile-time error occurs.
+
+        if (leftNameCategory == NameCategory.TYPE_NAME) {
+            SymbolReference<ResolvedTypeDeclaration> scopeTypeRef = JavaParserFactory.getContext(leftName, typeSolver)
+                    .solveType(NameLogic.nameAsString(leftName));
+            if (scopeTypeRef.isSolved()) {
+                ResolvedTypeDeclaration scopeType = scopeTypeRef.getCorrespondingDeclaration();
+                if (scopeType instanceof ResolvedReferenceTypeDeclaration) {
+                    ResolvedReferenceTypeDeclaration scopeRefType = scopeType.asReferenceType();
+                    if (scopeRefType.getAllMethods().stream().anyMatch(m -> m.getName().equals(rightName))) {
+                        return NameCategory.EXPRESSION_NAME;
+                    }
+                    if (scopeRefType.getAllFields().stream().anyMatch(f -> f.isStatic() && f.getName().equals(rightName))) {
+                        return NameCategory.EXPRESSION_NAME;
+                    }
+                    if (scopeRefType.hasInternalType(rightName)) {
+                        return NameCategory.TYPE_NAME;
+                    }
+                    return NameCategory.COMPILATION_ERROR;
+                } else {
+                    throw new UnsupportedOperationException("The name is a type but it has been resolved to something that is not a reference type");
+                }
+            } else {
+                throw new UnsolvedSymbolException("Unable to solve context type: " + NameLogic.nameAsString(leftName));
+            }
+        }
+
+        // * If the name to the left of the "." is reclassified as an ExpressionName, then this AmbiguousName is
+        //   reclassified as an ExpressionName. A later step determines whether or not a member with the name Identifier
+        //   actually exists.
+
+        if (leftNameCategory == NameCategory.EXPRESSION_NAME) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+
+        throw new UnsupportedOperationException("I do not know how to handle this semantic reclassification of ambiguous name categories");
+    }
+
+    private static NameCategory reclassificationOfContextuallyAmbiguousSimpleAmbiguousName(Node nameNode,
+                                                                                           TypeSolver typeSolver) {
+        // If the AmbiguousName is a simple name, consisting of a single Identifier:
+        //
+        // * If the Identifier appears within the scope (§6.3) of a local variable declaration (§14.4) or parameter
+        //   declaration (§8.4.1, §8.8.1, §14.20) or field declaration (§8.3) with that name, then the AmbiguousName is
+        //   reclassified as an ExpressionName.
+
+        String name = nameAsString(nameNode);
+        Context context = JavaParserFactory.getContext(nameNode, typeSolver);
+        if (context.localVariableDeclarationInScope(name).isPresent()) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+        if (context.parameterDeclarationInScope(name).isPresent()) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+        if (context.fieldDeclarationInScope(name).isPresent()) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+
+        // * Otherwise, if a field of that name is declared in the compilation unit (§7.3) containing the Identifier by
+        //   a single-static-import declaration (§7.5.3), or by a static-import-on-demand declaration (§7.5.4) then the
+        //   AmbiguousName is reclassified as an ExpressionName.
+        //
+        // * Otherwise, if the Identifier is a valid TypeIdentifier and appears within the scope (§6.3) of a top level
+        //   class (§8 (Classes)) or interface type declaration (§9 (Interfaces)), a local class declaration (§14.3) or
+        //   member type declaration (§8.5, §9.5) with that name, then the AmbiguousName is reclassified as a TypeName.
+        //
+        // * Otherwise, if the Identifier is a valid TypeIdentifier and a type of that name is declared in the
+        //   compilation unit (§7.3) containing the Identifier, either by a single-type-import declaration (§7.5.1), or
+        //   by a type-import-on-demand declaration (§7.5.2), or by a single-static-import declaration (§7.5.3), or by
+        //   a static-import-on-demand declaration (§7.5.4), then the AmbiguousName is reclassified as a TypeName.
+        //
+        // Otherwise, the AmbiguousName is reclassified as a PackageName. A later step determines whether or not a
+        // package of that name actually exists.
+
+        return NameCategory.PACKAGE_NAME;
+    }
+
+    /**
+     * See JLS 6.5.1 Syntactic Classification of a Name According to Context.
+     * <p>
+     * Most users do not want to call directly this method but call classifyReference instead.
+     */
+    public static NameCategory syntacticClassificationAccordingToContext(Node name) {
+
+        if (name.getParentNode().isPresent()) {
+            Node parent = name.getParentNode().get();
+            if (isAName(parent) && nameAsString(name).equals(nameAsString(parent))) {
+                return syntacticClassificationAccordingToContext(parent);
+            }
+        }
+
+        if (isSyntacticallyATypeName(name)) {
+            return NameCategory.TYPE_NAME;
+        }
+        if (isSyntacticallyAnExpressionName(name)) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+        if (isSyntacticallyAMethodName(name)) {
+            return NameCategory.METHOD_NAME;
+        }
+        if (isSyntacticallyAPackageOrTypeName(name)) {
+            return NameCategory.PACKAGE_OR_TYPE_NAME;
+        }
+        if (isSyntacticallyAAmbiguousName(name)) {
+            return NameCategory.AMBIGUOUS_NAME;
+        }
+        if (isSyntacticallyAModuleName(name)) {
+            return NameCategory.MODULE_NAME;
+        }
+        if (isSyntacticallyAPackageName(name)) {
+            return NameCategory.PACKAGE_NAME;
+        }
+
+        if (name instanceof NameExpr) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+        if (name instanceof FieldAccessExpr) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+        if (name instanceof ClassOrInterfaceType) {
+            return NameCategory.TYPE_NAME;
+        }
+        if (name.getParentNode().isPresent() && name.getParentNode().get() instanceof ClassOrInterfaceType) {
+            return NameCategory.TYPE_NAME;
+        }
+        if (name.getParentNode().isPresent() && name.getParentNode().get() instanceof FieldAccessExpr) {
+            return NameCategory.EXPRESSION_NAME;
+        }
+
+        throw new UnsupportedOperationException("Unable to classify category of name contained in "
+                + name.getParentNode().get().getClass().getSimpleName() + ". See " + name + " at " + name.getRange());
+    }
+
+    private static boolean isSyntacticallyAAmbiguousName(Node name) {
+        // A name is syntactically classified as an AmbiguousName in these contexts:
+        //
+        // 1. To the left of the "." in a qualified ExpressionName
+
+        if (whenParentIs(FieldAccessExpr.class, name, (p, c) -> p.getScope() == c)) {
+            return true;
+        }
+
+        // 2. To the left of the rightmost . that occurs before the "(" in a method invocation expression
+
+        if (whenParentIs(MethodCallExpr.class, name, (p, c) -> p.getScope().isPresent() && p.getScope().get() == c)) {
+            return true;
+        }
+
+        // 3. To the left of the "." in a qualified AmbiguousName
+        //
+        // 4. In the default value clause of an annotation type element declaration (§9.6.2)
+        //
+        // 5. To the right of an "=" in an an element-value pair (§9.7.1)
+
+        if (whenParentIs(MemberValuePair.class, name, (p, c) -> p.getValue() == c)) {
+            return true;
+        }
+
+        // 6. To the left of :: in a method reference expression (§15.13)
+        return false;
+    }
+
+    private static boolean isSyntacticallyAPackageOrTypeName(Node name) {
+        // A name is syntactically classified as a PackageOrTypeName in these contexts:
+        //
+        // 1. To the left of the "." in a qualified TypeName
+
+        if (whenParentIs(ClassOrInterfaceType.class, name, (p, c) -> p.getScope().isPresent() && p.getScope().get() == c && (isSyntacticallyATypeName(p) || isSyntacticallyAPackageOrTypeName(p)))) {
+            return true;
+        }
+
+        // 2. In a type-import-on-demand declaration (§7.5.2)
+
+        if (whenParentIs(ImportDeclaration.class, name, (p, c) ->
+                !p.isStatic() && p.isAsterisk() && p.getName() == name)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private static boolean isSyntacticallyAMethodName(Node name) {
+        // A name is syntactically classified as a MethodName in this context:
+        //
+        // 1. Before the "(" in a method invocation expression (§15.12)
+
+        if (whenParentIs(MethodCallExpr.class, name, (p, c) -> p.getName() == c)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private static boolean isSyntacticallyAModuleName(Node name) {
+        // A name is syntactically classified as a ModuleName in these contexts:
+        //
+        // 1. In a requires directive in a module declaration (§7.7.1)
+
+        if (whenParentIs(ModuleRequiresDirective.class, name, (p, c) -> p.getName() == name)) {
+            return true;
+        }
+
+        // 2. To the right of to in an exports or opens directive in a module declaration (§7.7.2)
+
+        if (whenParentIs(ModuleExportsDirective.class, name, (p, c) -> p.getModuleNames().contains(name))) {
+            return true;
+        }
+        if (whenParentIs(ModuleOpensDirective.class, name, (p, c) -> p.getModuleNames().contains(name))) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private static boolean isSyntacticallyAPackageName(Node name) {
+        // A name is syntactically classified as a PackageName in these contexts:
+        //
+        // 1. To the right of exports or opens in a module declaration
+        if (whenParentIs(ModuleExportsDirective.class, name, (p, c) -> p.getName() == name)) {
+            return true;
+        }
+        if (whenParentIs(ModuleOpensDirective.class, name, (p, c) -> p.getName() == name)) {
+            return true;
+        }
+        // 2. To the left of the "." in a qualified PackageName
+        if (whenParentIs(Name.class, name, (p, c) -> p.getQualifier().isPresent()
+                && p.getQualifier().get() == name
+                && isSyntacticallyAPackageName(p))) {
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean isSyntacticallyATypeName(Node name) {
+        // A name is syntactically classified as a TypeName in these contexts:
+        //
+        // The first eleven non-generic contexts (§6.1):
+        //
+        // 1. In a uses or provides directive in a module declaration (§7.7.1)
+
+        if (whenParentIs(ModuleUsesDirective.class, name, (p, c) -> p.getName() == c)) {
+            return true;
+        }
+        if (whenParentIs(ModuleProvidesDirective.class, name, (p, c) -> p.getName() == c)) {
+            return true;
+        }
+
+        // 2. In a single-type-import declaration (§7.5.1)
+
+        if (whenParentIs(ImportDeclaration.class, name, (p, c) ->
+                !p.isStatic() && !p.isAsterisk() && p.getName() == name)) {
+            return true;
+        }
+
+        // 3. To the left of the . in a single-static-import declaration (§7.5.3)
+
+        if (whenParentIs(Name.class, name, (largerName, c) ->
+                whenParentIs(ImportDeclaration.class, largerName, (importDecl, c2) ->
+                        importDecl.isStatic() && !importDecl.isAsterisk() && importDecl.getName() == c2)
+        )) {
+            return true;
+        }
+        if (whenParentIs(ImportDeclaration.class, name, (importDecl, c2) ->
+                importDecl.isStatic() && !importDecl.isAsterisk() && importDecl.getName() == c2)) {
+            return true;
+        }
+
+        // 4. To the left of the . in a static-import-on-demand declaration (§7.5.4)
+
+        if (whenParentIs(ImportDeclaration.class, name, (p, c) ->
+                p.isStatic() && p.isAsterisk() && p.getName() == name)) {
+            return true;
+        }
+
+        // 5. To the left of the ( in a constructor declaration (§8.8)
+
+        if (whenParentIs(ConstructorDeclaration.class, name, (p, c) -> p.getName() == name)) {
+            return true;
+        }
+
+        // 6. After the @ sign in an annotation (§9.7)
+
+        if (whenParentIs(AnnotationExpr.class, name, (p, c) -> p.getName() == name)) {
+            return true;
+        }
+
+        // 7. To the left of .class in a class literal (§15.8.2)
+
+        if (whenParentIs(ClassExpr.class, name, (p, c) -> p.getType() == c)) {
+            return true;
+        }
+
+        // 8. To the left of .this in a qualified this expression (§15.8.4)
+
+        if (whenParentIs(ThisExpr.class, name, (ne, c2) ->
+                ne.getTypeName().isPresent() && ne.getTypeName().get() == c2)) {
+            return true;
+        }
+
+        // 9. To the left of .super in a qualified superclass field access expression (§15.11.2)
+
+        if (whenParentIs(SuperExpr.class, name, (ne, c2) ->
+                ne.getTypeName().isPresent() && ne.getTypeName().get() == c2)) {
+            return true;
+        }
+
+        // 10. To the left of .Identifier or .super.Identifier in a qualified method invocation expression (§15.12)
+        //
+        // 11. To the left of .super:: in a method reference expression (§15.13)
+        //
+        // As the Identifier or dotted Identifier sequence that constitutes any ReferenceType (including a
+        // ReferenceType to the left of the brackets in an array type, or to the left of the < in a parameterized type,
+        // or in a non-wildcard type argument of a parameterized type, or in an extends or super clause of a wildcard
+        // type argument of a parameterized type) in the 16 contexts where types are used (§4.11):
+        //
+        // 1. In an extends or implements clause of a class declaration (§8.1.4, §8.1.5, §8.5, §9.5)
+        // 2. In an extends clause of an interface declaration (§9.1.3)
+
+        if (whenParentIs(ClassOrInterfaceDeclaration.class, name, (p, c) ->
+                p.getExtendedTypes().contains(c) || p.getImplementedTypes().contains(c))) {
+            return true;
+        }
+
+        // 3. The return type of a method (§8.4, §9.4) (including the type of an element of an annotation type (§9.6.1))
+
+        if (whenParentIs(MethodDeclaration.class, name, (p, c) ->
+                p.getType() == c)) {
+            return true;
+        }
+        if (whenParentIs(AnnotationMemberDeclaration.class, name, (p, c) ->
+                p.getType() == c)) {
+            return true;
+        }
+
+        // 4. In the throws clause of a method or constructor (§8.4.6, §8.8.5, §9.4)
+
+        if (whenParentIs(MethodDeclaration.class, name, (p, c) ->
+                p.getThrownExceptions().contains(c))) {
+            return true;
+        }
+        if (whenParentIs(ConstructorDeclaration.class, name, (p, c) ->
+                p.getThrownExceptions().contains(c))) {
+            return true;
+        }
+
+        // 5. In an extends clause of a type parameter declaration of a generic class, interface, method, or
+        //    constructor (§8.1.2, §9.1.2, §8.4.4, §8.8.4)
+        //
+        // 6. The type in a field declaration of a class or interface (§8.3, §9.3)
+
+        if (whenParentIs(VariableDeclarator.class, name, (p1, c1) ->
+                p1.getType() == c1 && whenParentIs(FieldDeclaration.class, p1, (p2, c2) ->
+                        p2.getVariables().contains(c2)))) {
+            return true;
+        }
+
+        // 7. The type in a formal parameter declaration of a method, constructor, or lambda expression
+        //    (§8.4.1, §8.8.1, §9.4, §15.27.1)
+
+        if (whenParentIs(Parameter.class, name, (p, c) ->
+                p.getType() == c)) {
+            return true;
+        }
+
+        // 8. The type of the receiver parameter of a method (§8.4.1)
+
+        if (whenParentIs(ReceiverParameter.class, name, (p, c) ->
+                p.getType() == c)) {
+            return true;
+        }
+
+        // 9. The type in a local variable declaration (§14.4, §14.14.1, §14.14.2, §14.20.3)
+
+        if (whenParentIs(VariableDeclarator.class, name, (p1, c1) ->
+                p1.getType() == c1 && whenParentIs(VariableDeclarationExpr.class, p1, (p2, c2) ->
+                        p2.getVariables().contains(c2)))) {
+            return true;
+        }
+
+        // 10. A type in an exception parameter declaration (§14.20)
+        //
+        // 11. In an explicit type argument list to an explicit constructor invocation statement or class instance
+        //     creation expression or method invocation expression (§8.8.7.1, §15.9, §15.12)
+
+        if (whenParentIs(ClassOrInterfaceType.class, name, (p, c) ->
+                p.getTypeArguments().isPresent() && p.getTypeArguments().get().contains(c))) {
+            return true;
+        }
+        if (whenParentIs(MethodCallExpr.class, name, (p, c) ->
+                p.getTypeArguments().isPresent() && p.getTypeArguments().get().contains(c))) {
+            return true;
+        }
+
+        // 12. In an unqualified class instance creation expression, either as the class type to be instantiated (§15.9)
+        //     or as the direct superclass or direct superinterface of an anonymous class to be instantiated (§15.9.5)
+
+        if (whenParentIs(ObjectCreationExpr.class, name, (p, c) ->
+                p.getType() == c)) {
+            return true;
+        }
+
+        // 13. The element type in an array creation expression (§15.10.1)
+
+        if (whenParentIs(ArrayCreationExpr.class, name, (p, c) ->
+                p.getElementType() == c)) {
+            return true;
+        }
+
+        // 14. The type in the cast operator of a cast expression (§15.16)
+
+        if (whenParentIs(CastExpr.class, name, (p, c) ->
+                p.getType() == c)) {
+            return true;
+        }
+
+        // 15. The type that follows the instanceof relational operator (§15.20.2)
+
+        if (whenParentIs(InstanceOfExpr.class, name, (p, c) ->
+                p.getType() == c)) {
+            return true;
+        }
+
+        // 16. In a method reference expression (§15.13), as the reference type to search for a member method or as the class type or array type to construct.
+
+        if (whenParentIs(TypeExpr.class, name, (p1, c1) ->
+                p1.getType() == c1 && whenParentIs(MethodReferenceExpr.class, p1, (p2, c2) ->
+                        p2.getScope() == c2)
+        )) {
+            return true;
+        }
+
+        // The extraction of a TypeName from the identifiers of a ReferenceType in the 16 contexts above is intended to
+        // apply recursively to all sub-terms of the ReferenceType, such as its element type and any type arguments.
+        //
+        // For example, suppose a field declaration uses the type p.q.Foo[]. The brackets of the array type are ignored,
+        // and the term p.q.Foo is extracted as a dotted sequence of Identifiers to the left of the brackets in an array
+        // type, and classified as a TypeName. A later step determines which of p, q, and Foo is a type name or a
+        // package name.
+        //
+        // As another example, suppose a cast operator uses the type p.q.Foo<? extends String>. The term p.q.Foo is
+        // again extracted as a dotted sequence of Identifier terms, this time to the left of the < in a parameterized
+        // type, and classified as a TypeName. The term String is extracted as an Identifier in an extends clause of a
+        // wildcard type argument of a parameterized type, and classified as a TypeName.
+        return false;
+    }
+
+    private static boolean isSyntacticallyAnExpressionName(Node name) {
+        // A name is syntactically classified as an ExpressionName in these contexts:
+        //
+        // 1. As the qualifying expression in a qualified superclass constructor invocation (§8.8.7.1)
+
+        if (whenParentIs(NameExpr.class, name, (nameExpr, c) ->
+                nameExpr.getName() == c && whenParentIs(ExplicitConstructorInvocationStmt.class, nameExpr, (ne, c2) ->
+                        ne.getExpression().isPresent() && ne.getExpression().get() == c2)
+        )) {
+            return true;
+        }
+        if (whenParentIs(ExplicitConstructorInvocationStmt.class, name, (ne, c2) ->
+                ne.getExpression().isPresent() && ne.getExpression().get() == c2)) {
+            return true;
+        }
+
+        // 2. As the qualifying expression in a qualified class instance creation expression (§15.9)
+
+        if (whenParentIs(NameExpr.class, name, (nameExpr, c) ->
+                nameExpr.getName() == c && whenParentIs(ObjectCreationExpr.class, nameExpr, (ne, c2) ->
+                        ne.getScope().isPresent() && ne.getScope().get() == c2)
+        )) {
+            return true;
+        }
+        if (whenParentIs(ObjectCreationExpr.class, name, (ne, c2) ->
+                ne.getScope().isPresent() && ne.getScope().get() == c2)) {
+            return true;
+        }
+
+        // 3. As the array reference expression in an array access expression (§15.10.3)
+
+        if (whenParentIs(NameExpr.class, name, (nameExpr, c) ->
+                nameExpr.getName() == c && whenParentIs(ArrayAccessExpr.class, nameExpr, (ne, c2) ->
+                        ne.getName() == c2)
+        )) {
+            return true;
+        }
+        if (whenParentIs(ArrayAccessExpr.class, name, (ne, c2) ->
+                ne.getName() == c2)) {
+            return true;
+        }
+
+        // 4. As a PostfixExpression (§15.14)
+
+        if (whenParentIs(NameExpr.class, name, (nameExpr, c) ->
+                nameExpr.getName() == c && whenParentIs(UnaryExpr.class, nameExpr, (ne, c2) ->
+                        ne.getExpression() == c2 && ne.isPostfix())
+        )) {
+            return true;
+        }
+        if (whenParentIs(UnaryExpr.class, name, (ne, c2) ->
+                ne.getExpression() == c2 && ne.isPostfix())) {
+            return true;
+        }
+
+        // 5. As the left-hand operand of an assignment operator (§15.26)
+
+        if (whenParentIs(NameExpr.class, name, (nameExpr, c) ->
+                nameExpr.getName() == c && whenParentIs(AssignExpr.class, nameExpr, (ne, c2) ->
+                        ne.getTarget() == c2)
+        )) {
+            return true;
+        }
+        if (whenParentIs(AssignExpr.class, name, (ne, c2) ->
+                ne.getTarget() == c2)) {
+            return true;
+        }
+
+        // 6. As a VariableAccess in a try-with-resources statement (§14.20.3)
+
+        if (whenParentIs(NameExpr.class, name, (nameExpr, c) ->
+                nameExpr.getName() == c && whenParentIs(TryStmt.class, nameExpr, (ne, c2) ->
+                        ne.getResources().contains(c2))
+        )) {
+            return true;
+        }
+        if (whenParentIs(NameExpr.class, name, (p1 /*NameExpr*/, c1 /*SimpleName*/) ->
+                p1.getName() == c1 && whenParentIs(VariableDeclarator.class, p1, (p2, c2) ->
+                        p2.getInitializer().isPresent() && p2.getInitializer().get() == c2 && whenParentIs(VariableDeclarationExpr.class, p2, (p3, c3) ->
+                                p3.getVariables().contains(c3) && whenParentIs(TryStmt.class, p3, (p4, c4) ->
+                                        p4.getResources().contains(c4)
+                                )
+                        ))
+        )) {
+            return true;
+        }
+        if (whenParentIs(TryStmt.class, name, (ne, c2) ->
+                ne.getResources().contains(c2))) {
+            return true;
+        }
+        if (whenParentIs(VariableDeclarator.class, name, (p2, c2) ->
+                p2.getInitializer().isPresent() && p2.getInitializer().get() == c2 && whenParentIs(VariableDeclarationExpr.class, p2, (p3, c3) ->
+                        p3.getVariables().contains(c3) && whenParentIs(TryStmt.class, p3, (p4, c4) ->
+                                p4.getResources().contains(c4)
+                        )
+                ))) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Return the string representation of the name
+     */
+    public static String nameAsString(Node name) {
+        if (!isAName(name)) {
+            throw new IllegalArgumentException("A name was expected");
+        }
+        if (name instanceof Name) {
+            return ((Name) name).asString();
+        } else if (name instanceof SimpleName) {
+            return ((SimpleName) name).getIdentifier();
+        } else if (name instanceof ClassOrInterfaceType) {
+            return ((ClassOrInterfaceType) name).asString();
+        } else if (name instanceof FieldAccessExpr) {
+            FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) name;
+            if (isAName(fieldAccessExpr.getScope())) {
+                return nameAsString(fieldAccessExpr.getScope()) + "." + nameAsString(fieldAccessExpr.getName());
+            } else {
+                throw new IllegalArgumentException();
+            }
+        } else if (name instanceof NameExpr) {
+            return ((NameExpr) name).getNameAsString();
+        } else {
+            throw new UnsupportedOperationException("Unknown type of name found: " + name + " ("
+                    + name.getClass().getCanonicalName() + ")");
+        }
+    }
+
+    private interface PredicateOnParentAndChild<P extends Node, C extends Node> {
+        boolean isSatisfied(P parent, C child);
+    }
+
+    private static <P extends Node, C extends Node> boolean whenParentIs(Class<P> parentClass, C child) {
+        return whenParentIs(parentClass, child, (p, c) -> true);
+    }
+
+    private static <P extends Node, C extends Node> boolean whenParentIs(
+            Class<P> parentClass,
+            C child,
+            PredicateOnParentAndChild<P, C> predicate) {
+        if (child.getParentNode().isPresent()) {
+            Node parent = child.getParentNode().get();
+            return parentClass.isInstance(parent) && predicate.isSatisfied(parentClass.cast(parent), child);
+        } else {
+            return false;
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameRole.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameRole.java
new file mode 100644
index 0000000..57ea432
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/naming/NameRole.java
@@ -0,0 +1,9 @@
+package com.github.javaparser.symbolsolver.resolution.naming;
+
+/**
+ * Each Name can be part either of a Declaration or a Reference to a Declaration.
+ */
+public enum NameRole {
+    DECLARATION,
+    REFERENCE
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/FalseBound.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/FalseBound.java
index b1554db..b9ef071 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/FalseBound.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/FalseBound.java
@@ -4,7 +4,6 @@
 import com.github.javaparser.symbolsolver.resolution.typeinference.InferenceVariable;
 import com.github.javaparser.symbolsolver.resolution.typeinference.InferenceVariableSubstitution;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
 
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBound.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBound.java
index 357e7a0..482fbca 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBound.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBound.java
@@ -2,7 +2,6 @@
 
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.resolution.typeinference.*;
-import com.github.javaparser.utils.Pair;
 
 import java.util.HashSet;
 import java.util.Optional;
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolver.java
index 0811ef1..5e9fb5d 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolver.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolver.java
@@ -20,21 +20,29 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.jar.JarFile;
 import java.util.zip.ZipEntry;
 
 /**
+ * Will let the symbol solver look inside an Android aar file while solving types.
+ * (It will look inside the contained classes.jar)
+ *
  * @author Federico Tomassetti
  */
 public class AarTypeSolver implements TypeSolver {
 
-    private TypeSolver parent;
-    private File aarFile;
     private JarTypeSolver delegate;
 
-    public AarTypeSolver(File aarFile) throws IOException {
-        this.aarFile = aarFile;
+    public AarTypeSolver(String aarFile) throws IOException {
+        this(new File(aarFile));
+    }
 
+    public AarTypeSolver(Path aarFile) throws IOException {
+        this(aarFile.toFile());
+    }
+
+    public AarTypeSolver(File aarFile) throws IOException {
         JarFile jarFile = new JarFile(aarFile);
         ZipEntry classesJarEntry = jarFile.getEntry("classes.jar");
         if (classesJarEntry == null) {
@@ -45,12 +53,12 @@
 
     @Override
     public TypeSolver getParent() {
-        return parent;
+        return delegate.getParent();
     }
 
     @Override
     public void setParent(TypeSolver parent) {
-        this.parent = parent;
+        delegate.setParent(parent);
     }
 
     @Override
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ClassLoaderTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ClassLoaderTypeSolver.java
new file mode 100644
index 0000000..ef7897a
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ClassLoaderTypeSolver.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016-2018 The JavaParser Team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
+
+import java.util.Optional;
+
+/**
+ * This TypeSolver wraps a ClassLoader. It can solve all types that the given ClassLoader can load.
+ * This is intended to be used with custom classloaders. To support typical cases based on reflection
+ * just use the ReflectionTypeSolver
+ *
+ * @author Federico Tomassetti
+ */
+public class ClassLoaderTypeSolver implements TypeSolver {
+
+    private TypeSolver parent;
+    private ClassLoader classLoader;
+
+    public ClassLoaderTypeSolver(ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    public TypeSolver getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(TypeSolver parent) {
+        this.parent = parent;
+    }
+
+    protected boolean filterName(String name) {
+        return true;
+    }
+
+    @Override
+    public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name) {
+        if (filterName(name)) {
+            try {
+                // Some implementations could return null when the class was loaded through the bootstrap classloader
+                // see https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getClassLoader--
+                if (classLoader == null) {
+                    throw new RuntimeException(
+                            "The ClassLoaderTypeSolver has been probably loaded through the bootstrap class loader. This usage is not supported by the JavaSymbolSolver");
+                }
+
+                Class<?> clazz = classLoader.loadClass(name);
+                return SymbolReference.solved(ReflectionFactory.typeDeclarationFor(clazz, getRoot()));
+            } catch (NoClassDefFoundError e) {
+                // We can safely ignore this one because it is triggered when there are package names which are almost the
+                // same as class name, with the exclusion of the case.
+                // For example:
+                // java.lang.NoClassDefFoundError: com/github/javaparser/printer/ConcreteSyntaxModel
+                // (wrong name: com/github/javaparser/printer/concretesyntaxmodel)
+                // note that this exception seems to be thrown only on certain platform (mac yes, linux no)
+                return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
+            } catch (ClassNotFoundException e) {
+                // it could be an inner class
+                int lastDot = name.lastIndexOf('.');
+                if (lastDot == -1) {
+                    return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
+                } else {
+                    String parentName = name.substring(0, lastDot);
+                    String childName = name.substring(lastDot + 1);
+                    SymbolReference<ResolvedReferenceTypeDeclaration> parent = tryToSolveType(parentName);
+                    if (parent.isSolved()) {
+                        Optional<ResolvedReferenceTypeDeclaration> innerClass = parent.getCorrespondingDeclaration()
+                                .internalTypes()
+                                .stream().filter(it -> it.getName().equals(childName)).findFirst();
+                        return innerClass.map(SymbolReference::solved)
+                                .orElseGet(() -> SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class));
+                    } else {
+                        return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
+                    }
+                }
+            }
+        } else {
+            return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java
index fe9f375..bc66f58 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java
@@ -16,28 +16,58 @@
 
 package com.github.javaparser.symbolsolver.resolution.typesolvers;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
+ * A container for type solvers. All solving is done by the contained type solvers.
+ * This helps you when an API asks for a single type solver, but you need several.
+ *
  * @author Federico Tomassetti
  */
 public class CombinedTypeSolver implements TypeSolver {
 
     private TypeSolver parent;
     private List<TypeSolver> elements = new ArrayList<>();
+    
+    /**
+     * A predicate which determines what to do if an exception is raised during the parsing process.
+     * If it returns <code>true</code> the exception will be ignored, and solving will continue using the next solver in line.
+     * If it returns <code>false</code> the exception will be thrown, stopping the solving process.
+     * 
+     * Main use case for this is to circumvent bugs or missing functionality in some type solvers.
+     * If for example solver A has a bug resulting in a {@link NullPointerException}, you could use a {@link ExceptionHandlers#getTypeBasedWhitelist(Class...) whitelist} to ignore that type of exception.
+     * A secondary solver would then be able to step in when such an error occurs.
+     * 
+     * @see #CombinedTypeSolver(Predicate, TypeSolver...)
+     * @see #setExceptionHandler(Predicate)
+     */
+    private Predicate<Exception> exceptionHandler;
 
     public CombinedTypeSolver(TypeSolver... elements) {
+        this(ExceptionHandlers.IGNORE_NONE, elements);
+    }
+
+    /** @see #exceptionHandler */
+    public CombinedTypeSolver(Predicate<Exception> exceptionHandler, TypeSolver... elements) {
+        setExceptionHandler(exceptionHandler);
+
         for (TypeSolver el : elements) {
             add(el);
         }
     }
 
+    /** @see #exceptionHandler */
+    public void setExceptionHandler(Predicate<Exception> exceptionHandler) {
+        this.exceptionHandler = exceptionHandler;
+    }
+
     @Override
     public TypeSolver getParent() {
         return parent;
@@ -56,9 +86,15 @@
     @Override
     public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name) {
         for (TypeSolver ts : elements) {
-            SymbolReference<ResolvedReferenceTypeDeclaration> res = ts.tryToSolveType(name);
-            if (res.isSolved()) {
-                return res;
+            try {
+                SymbolReference<ResolvedReferenceTypeDeclaration> res = ts.tryToSolveType(name);
+                if (res.isSolved()) {
+                    return res;
+                }
+            } catch (Exception e) {
+                if (!exceptionHandler.test(e)) { // we shouldn't ignore this exception
+                    throw e;
+                }
             }
         }
         return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
@@ -73,4 +109,84 @@
             throw new UnsolvedSymbolException(name);
         }
     }
+
+    /**
+     * Provides some convenience exception handler implementations
+     * @see CombinedTypeSolver#setExceptionHandler(Predicate)
+     */
+    public static class ExceptionHandlers {
+
+        /** Doesn't ignore any exceptions (default) */
+        public static final Predicate<Exception> IGNORE_NONE = e -> false;
+
+        /** Ignores all exceptions */
+        public static final Predicate<Exception> IGNORE_ALL = e -> true;
+
+        /**
+         * Ignores any exception that is {@link Class#isAssignableFrom(Class) assignable from}
+         * {@link UnsupportedOperationException}.
+         * 
+         * @see #getTypeBasedWhitelist(Class...)
+         */
+        public static final Predicate<Exception> IGNORE_UNSUPPORTED_OPERATION = getTypeBasedWhitelist(
+                UnsupportedOperationException.class);
+
+        /**
+         * Ignores any exception that is {@link Class#isAssignableFrom(Class) assignable from}
+         * {@link UnsolvedSymbolException}.
+         * 
+         * @see #getTypeBasedWhitelist(Class...)
+         */
+        public static final Predicate<Exception> IGNORE_UNSOLVED_SYMBOL = getTypeBasedWhitelist(
+                UnsolvedSymbolException.class);
+
+        /**
+         * Ignores any exception that is {@link Class#isAssignableFrom(Class) assignable from} either
+         * {@link UnsolvedSymbolException} or {@link UnsupportedOperationException}.
+         * 
+         * @see #IGNORE_UNSOLVED_SYMBOL
+         * @see #IGNORE_UNSUPPORTED_OPERATION
+         * @see #getTypeBasedWhitelist(Class...)
+         */
+        public static final Predicate<Exception> IGNORE_UNSUPPORTED_AND_UNSOLVED = getTypeBasedWhitelist(
+                UnsupportedOperationException.class, UnsolvedSymbolException.class);
+
+        /**
+         * @see CombinedTypeSolver#setExceptionHandler(Predicate)
+         * @see #getTypeBasedWhitelist(Class...)
+         * 
+         * @return A filter that ignores an exception if <b>none</b> of the listed classes are
+         *         {@link Class#isAssignableFrom(Class) assignable from}
+         *         the thrown exception class.
+         */
+        public static Predicate<Exception> getTypeBasedBlacklist(Class<? extends Exception>... blacklist) {
+            return e -> {
+                for (Class<? extends Exception> clazz : blacklist) {
+                    if (clazz.isAssignableFrom(e.getClass())) {
+                        return false;
+                    }
+                }
+                return true;
+            };
+        }
+
+        /**
+         * @see CombinedTypeSolver#setExceptionHandler(Predicate)
+         * @see #getTypeBasedBlacklist(Class...)
+         * 
+         * @return A filter that ignores an exception if <b>any</b> of the listed classes are
+         *         {@link Class#isAssignableFrom(Class) assignable from}
+         *         the thrown exception class.
+         */
+        public static Predicate<Exception> getTypeBasedWhitelist(Class<? extends Exception>... whitelist) {
+            return e -> {
+                for (Class<? extends Exception> clazz : whitelist) {
+                    if (clazz.isAssignableFrom(e.getClass())) {
+                        return true;
+                    }
+                }
+                return false;
+            };
+        }
+    }
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java
index 9ce9cbb..62270bd 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java
@@ -24,6 +24,7 @@
 import javassist.NotFoundException;
 
 import java.io.*;
+import java.nio.file.Path;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
@@ -31,6 +32,8 @@
 import java.util.jar.JarFile;
 
 /**
+ * Will let the symbol solver look inside a jar file while solving types.
+ *
  * @author Federico Tomassetti
  */
 public class JarTypeSolver implements TypeSolver {
@@ -41,6 +44,14 @@
     private Map<String, ClasspathElement> classpathElements = new HashMap<>();
     private ClassPool classPool = new ClassPool(false);
 
+    public JarTypeSolver(Path pathToJar) throws IOException {
+        this(pathToJar.toFile());
+    }
+
+    public JarTypeSolver(File pathToJar) throws IOException {
+        this(pathToJar.getCanonicalPath());
+    }
+
     public JarTypeSolver(String pathToJar) throws IOException {
         addPathToJar(pathToJar);
     }
@@ -64,15 +75,10 @@
 
         byte[] buffer = new byte[8 * 1024];
 
-        try {
-            OutputStream output = new FileOutputStream(tempFile);
-            try {
-                int bytesRead;
-                while ((bytesRead = inputStream.read(buffer)) != -1) {
-                    output.write(buffer, 0, bytesRead);
-                }
-            } finally {
-                output.close();
+        try (OutputStream output = new FileOutputStream(tempFile)) {
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                output.write(buffer, 0, bytesRead);
             }
         } finally {
             inputStream.close();
@@ -92,13 +98,13 @@
             throw new RuntimeException(e);
         }
         JarFile jarFile = new JarFile(pathToJar);
-        JarEntry entry = null;
+        JarEntry entry;
         Enumeration<JarEntry> e = jarFile.entries();
         while (e.hasMoreElements()) {
             entry = e.nextElement();
             if (entry != null && !entry.isDirectory() && entry.getName().endsWith(".class")) {
                 String name = entryPathToClassName(entry.getName());
-                classpathElements.put(name, new ClasspathElement(jarFile, entry, name));
+                classpathElements.put(name, new ClasspathElement(jarFile, entry));
             }
         }
     }
@@ -150,12 +156,10 @@
     private class ClasspathElement {
         private JarFile jarFile;
         private JarEntry entry;
-        private String path;
 
-        ClasspathElement(JarFile jarFile, JarEntry entry, String path) {
+        ClasspathElement(JarFile jarFile, JarEntry entry) {
             this.jarFile = jarFile;
             this.entry = entry;
-            this.path = path;
         }
 
         CtClass toCtClass() throws IOException {
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java
index 17e335e..52b4ab9 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java
@@ -17,6 +17,7 @@
 package com.github.javaparser.symbolsolver.resolution.typesolvers;
 
 import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParserConfiguration;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
@@ -28,32 +29,64 @@
 
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
-import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+import static com.github.javaparser.ParserConfiguration.LanguageLevel.BLEEDING_EDGE;
+import static com.github.javaparser.Providers.provider;
+
 /**
+ * Defines a directory containing source code that should be used for solving symbols.
+ * The directory must correspond to the root package of the files within.
+ *
  * @author Federico Tomassetti
  */
 public class JavaParserTypeSolver implements TypeSolver {
 
-    private File srcDir;
+    private final Path srcDir;
+    private final JavaParser javaParser;
 
     private TypeSolver parent;
 
-    private Cache<String, Optional<CompilationUnit>> parsedFiles = CacheBuilder.newBuilder().softValues().build();
-    private Cache<String, List<CompilationUnit>> parsedDirectories = CacheBuilder.newBuilder().softValues().build();
-    private Cache<String, SymbolReference<ResolvedReferenceTypeDeclaration>> foundTypes = CacheBuilder.newBuilder().softValues().build();
+    private final Cache<Path, Optional<CompilationUnit>> parsedFiles = CacheBuilder.newBuilder().softValues().build();
+    private final Cache<Path, List<CompilationUnit>> parsedDirectories = CacheBuilder.newBuilder().softValues().build();
+    private final Cache<String, SymbolReference<ResolvedReferenceTypeDeclaration>> foundTypes = CacheBuilder.newBuilder().softValues().build();
 
     public JavaParserTypeSolver(File srcDir) {
-        if (!srcDir.exists() || !srcDir.isDirectory()) {
-            throw new IllegalStateException("SrcDir does not exist or is not a directory: " + srcDir.getAbsolutePath());
+        this(srcDir.toPath());
+    }
+
+    public JavaParserTypeSolver(String srcDir) {
+        this(new File(srcDir));
+    }
+
+    public JavaParserTypeSolver(File srcDir, ParserConfiguration parserConfiguration) {
+        this(srcDir.toPath(), parserConfiguration);
+    }
+
+    public JavaParserTypeSolver(String srcDir, ParserConfiguration parserConfiguration) {
+        this(new File(srcDir), parserConfiguration);
+    }
+
+    public JavaParserTypeSolver(Path srcDir, ParserConfiguration parserConfiguration) {
+        if (!Files.exists(srcDir) || !Files.isDirectory(srcDir)) {
+            throw new IllegalStateException("SrcDir does not exist or is not a directory: " + srcDir);
         }
         this.srcDir = srcDir;
+        javaParser = new JavaParser(parserConfiguration);
+    }
+
+    public JavaParserTypeSolver(Path srcDir) {
+        this(srcDir,
+                new ParserConfiguration()
+                        .setLanguageLevel(BLEEDING_EDGE));
     }
 
     @Override
@@ -74,38 +107,51 @@
         this.parent = parent;
     }
 
-
-    private Optional<CompilationUnit> parse(File srcFile) {
+    private Optional<CompilationUnit> parse(Path srcFile) {
         try {
-            return parsedFiles.get(srcFile.getAbsolutePath(), () -> {
-                Optional<CompilationUnit> cu;
+            return parsedFiles.get(srcFile.toAbsolutePath(), () -> {
                 try {
-                    cu = Optional.of(JavaParser.parse(srcFile));
+                    if (!Files.exists(srcFile) || !Files.isRegularFile(srcFile)) {
+                        return Optional.empty();
+                    }
+                    return javaParser.parse(COMPILATION_UNIT, provider(srcFile))
+                            .getResult()
+                            .map(cu -> cu.setStorage(srcFile));
                 } catch (FileNotFoundException e) {
-                    cu = Optional.empty();
-                } catch (RuntimeException e) {
-                    throw new RuntimeException("Issue while parsing " + srcFile.getAbsolutePath(), e);
+                    throw new RuntimeException("Issue while parsing while type solving: " + srcFile.toAbsolutePath(), e);
                 }
-                return cu;
             });
         } catch (ExecutionException e) {
             throw new RuntimeException(e);
         }
     }
 
-    private List<CompilationUnit> parseDirectory(File srcDirectory) {
+    /**
+     * Note that this parse only files directly contained in this directory.
+     * It does not traverse recursively all children directory.
+     */
+    private List<CompilationUnit> parseDirectory(Path srcDirectory) {
+        return parseDirectory(srcDirectory, false);
+    }
+
+    private List<CompilationUnit> parseDirectoryRecursively(Path srcDirectory) {
+        return parseDirectory(srcDirectory, true);
+    }
+
+    private List<CompilationUnit> parseDirectory(Path srcDirectory, boolean recursively) {
         try {
-            return parsedDirectories.get(srcDirectory.getAbsolutePath(), () -> {
+            return parsedDirectories.get(srcDirectory.toAbsolutePath(), () -> {
                 List<CompilationUnit> units = new ArrayList<>();
-                File[] files = srcDirectory.listFiles();
-                if (files != null) {
-                    for (File file : files) {
-                        if (file.getName().toLowerCase().endsWith(".java")) {
-                            Optional<CompilationUnit> unit = parse(file);
-                            if (unit.isPresent()) {
-                                units.add(unit.get());
-                            }
-                        }
+                if(Files.exists(srcDirectory)) {
+                    try (DirectoryStream<Path> srcDirectoryStream = Files.newDirectoryStream(srcDirectory)) {
+                        srcDirectoryStream
+                                .forEach(file -> {
+                                    if (file.getFileName().toString().toLowerCase().endsWith(".java")) {
+                                        parse(file).ifPresent(units::add);
+                                    } else if (recursively && file.toFile().isDirectory()) {
+                                        units.addAll(parseDirectoryRecursively(file));
+                                    }
+                                });
                     }
                 }
                 return units;
@@ -113,6 +159,7 @@
         } catch (ExecutionException e) {
             throw new RuntimeException(e);
         }
+
     }
 
     @Override
@@ -136,35 +183,39 @@
         String[] nameElements = name.split("\\.");
 
         for (int i = nameElements.length; i > 0; i--) {
-            String filePath = srcDir.getAbsolutePath();
+            StringBuilder filePath = new StringBuilder(srcDir.toAbsolutePath().toString());
             for (int j = 0; j < i; j++) {
-                filePath += "/" + nameElements[j];
+                filePath.append("/")
+                        .append(nameElements[j]);
             }
-            filePath += ".java";
+            filePath.append(".java");
 
-            String typeName = "";
+            StringBuilder typeName = new StringBuilder();
             for (int j = i - 1; j < nameElements.length; j++) {
                 if (j != i - 1) {
-                    typeName += ".";
+                    typeName.append(".");
                 }
-                typeName += nameElements[j];
+                typeName.append(nameElements[j]);
             }
 
-            File srcFile = new File(filePath);
+            // As an optimization we first try to look in the canonical position where we expect to find the file
+            Path srcFile = Paths.get(filePath.toString());
             {
                 Optional<CompilationUnit> compilationUnit = parse(srcFile);
                 if (compilationUnit.isPresent()) {
-                    Optional<com.github.javaparser.ast.body.TypeDeclaration<?>> astTypeDeclaration = Navigator.findType(compilationUnit.get(), typeName);
+                    Optional<com.github.javaparser.ast.body.TypeDeclaration<?>> astTypeDeclaration = Navigator.findType(compilationUnit.get(), typeName.toString());
                     if (astTypeDeclaration.isPresent()) {
                         return SymbolReference.solved(JavaParserFacade.get(this).getTypeDeclaration(astTypeDeclaration.get()));
                     }
                 }
             }
 
+            // If this is not possible we parse all files
+            // We try just in the same package, for classes defined in a file not named as the class itself
             {
-                List<CompilationUnit> compilationUnits = parseDirectory(srcFile.getParentFile());
+                List<CompilationUnit> compilationUnits = parseDirectory(srcFile.getParent());
                 for (CompilationUnit compilationUnit : compilationUnits) {
-                    Optional<com.github.javaparser.ast.body.TypeDeclaration<?>> astTypeDeclaration = Navigator.findType(compilationUnit, typeName);
+                    Optional<com.github.javaparser.ast.body.TypeDeclaration<?>> astTypeDeclaration = Navigator.findType(compilationUnit, typeName.toString());
                     if (astTypeDeclaration.isPresent()) {
                         return SymbolReference.solved(JavaParserFacade.get(this).getTypeDeclaration(astTypeDeclaration.get()));
                     }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java
index 8e05473..e27aab1 100644
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Federico Tomassetti
+ * Copyright (C) 2016-2018 The JavaParser Team.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,79 +16,38 @@
 
 package com.github.javaparser.symbolsolver.resolution.typesolvers;
 
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
-
-import java.util.Optional;
-
 /**
+ * Uses reflection to resolve types.
+ * Classes on the classpath used to run your application will be found.
+ * No source code is available for the resolved types.
+ *
  * @author Federico Tomassetti
  */
-public class ReflectionTypeSolver implements TypeSolver {
+public class ReflectionTypeSolver extends ClassLoaderTypeSolver {
 
-    private TypeSolver parent;
+    private final boolean jreOnly;
 
+    /**
+     * @param jreOnly if true, will only resolve types from the java or javax packages.
+     * This is an easy way to say "I need a JRE to solve classes, and the one that is currently running is fine."
+     * If false, will resolve any kind of type.
+     */
     public ReflectionTypeSolver(boolean jreOnly) {
+        super(ReflectionTypeSolver.class.getClassLoader());
         this.jreOnly = jreOnly;
     }
 
+    /**
+     * Resolves classes from the JRE that is currently running.
+     * (It calls the other constructor with "true".)
+     */
     public ReflectionTypeSolver() {
         this(true);
     }
 
-    private boolean jreOnly;
-
     @Override
-    public TypeSolver getParent() {
-        return parent;
-    }
-
-    @Override
-    public void setParent(TypeSolver parent) {
-        this.parent = parent;
-    }
-
-    @Override
-    public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name) {
-        if (!jreOnly || (name.startsWith("java.") || name.startsWith("javax."))) {
-            try {
-                ClassLoader classLoader = ReflectionTypeSolver.class.getClassLoader();
-
-                // Some implementations could return null when the class was loaded through the bootstrap classloader
-                // see https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getClassLoader--
-                if (classLoader == null) {
-                    throw new RuntimeException("The ReflectionTypeSolver has been probably loaded through the bootstrap class loader. This usage is not supported by the JavaSymbolSolver");
-                }
-
-                Class<?> clazz = classLoader.loadClass(name);
-                return SymbolReference.solved(ReflectionFactory.typeDeclarationFor(clazz, getRoot()));
-            } catch (ClassNotFoundException e) {
-                // it could be an inner class
-                int lastDot = name.lastIndexOf('.');
-                if (lastDot == -1) {
-                    return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
-                } else {
-                    String parentName = name.substring(0, lastDot);
-                    String childName = name.substring(lastDot + 1);
-                    SymbolReference<ResolvedReferenceTypeDeclaration> parent = tryToSolveType(parentName);
-                    if (parent.isSolved()) {
-                        Optional<ResolvedReferenceTypeDeclaration> innerClass = parent.getCorrespondingDeclaration().internalTypes()
-                                .stream().filter(it -> it.getName().equals(childName)).findFirst();
-                        if (innerClass.isPresent()) {
-                            return SymbolReference.solved(innerClass.get());
-                        } else {
-                            return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
-                        }
-                    } else {
-                        return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
-                    }
-                }
-            }
-        } else {
-            return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
-        }
+    protected boolean filterName(String name) {
+        return !jreOnly || (name.startsWith("java.") || name.startsWith("javax."));
     }
 
 }
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategy.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategy.java
new file mode 100644
index 0000000..8296676
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategy.java
@@ -0,0 +1,81 @@
+package com.github.javaparser.symbolsolver.utils;
+
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.utils.CollectionStrategy;
+import com.github.javaparser.utils.Log;
+import com.github.javaparser.utils.ProjectRoot;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+import static java.nio.file.FileVisitResult.SKIP_SUBTREE;
+
+/**
+ * {@link CollectionStrategy} which collects all SourceRoots and initialises the TypeSolver and returns the SourceRoots configured
+ * with the TypeSolver in a ProjectRoot object.
+ */
+public class SymbolSolverCollectionStrategy implements CollectionStrategy {
+
+    private final ParserConfiguration parserConfiguration;
+    private final CombinedTypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(false));
+
+    public SymbolSolverCollectionStrategy() {
+        this(new ParserConfiguration());
+    }
+
+    public SymbolSolverCollectionStrategy(ParserConfiguration parserConfiguration) {
+        this.parserConfiguration = parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver));
+    }
+
+    @Override
+    public ProjectRoot collect(Path path) {
+        ProjectRoot projectRoot = new ProjectRoot(path, parserConfiguration);
+        try {
+            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+                private Path current_root;
+                private PathMatcher javaMatcher = getPathMatcher("glob:**.java");
+                private PathMatcher jarMatcher = getPathMatcher("glob:**.jar");
+
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    if (javaMatcher.matches(file)) {
+                        if (current_root == null || !file.startsWith(current_root)) {
+                            current_root = getRoot(file).orElse(null);
+                        }
+                    } else if (jarMatcher.matches(file)) {
+                        typeSolver.add(new JarTypeSolver(file.toString()));
+                    }
+                    return CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+                    if (Files.isHidden(dir)) {
+                        return SKIP_SUBTREE;
+                    }
+                    return CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
+                    if (current_root != null && Files.isSameFile(dir, current_root)) {
+                        projectRoot.addSourceRoot(dir);
+                        typeSolver.add(new JavaParserTypeSolver(current_root.toFile()));
+                        current_root = null;
+                    }
+                    return CONTINUE;
+                }
+            });
+        } catch (IOException e) {
+            Log.error(e, "Unable to walk %s", () -> path);
+        }
+        return projectRoot;
+    }
+}
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverQuickSetup.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverQuickSetup.java
deleted file mode 100644
index e6d3d53..0000000
--- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/utils/SymbolSolverQuickSetup.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
- * Copyright (C) 2011, 2013-2018 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.symbolsolver.utils;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseProblemException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import com.github.javaparser.utils.Log;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.nio.file.*;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-
-import static com.github.javaparser.utils.Utils.assertNotNull;
-import static java.nio.file.FileVisitResult.*;
-
-/**
- * Utility class to add all jars and roots of java files of the provided path to a TypeSolver instance.
- * It traverses the file directory tree and adds all files ending in either .java or .jar.
- */
-public class SymbolSolverQuickSetup {
-
-    public interface DirFilter {
-        boolean filter(Path path);
-    }
-
-    private final Path root;
-    private CombinedTypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(false));
-    private DirFilter dirFilter = path -> false;
-
-    public SymbolSolverQuickSetup(Path root) {
-        assertNotNull(root);
-        if (!Files.isDirectory(root)) {
-            throw new IllegalArgumentException("Only directories are allowed as root path!");
-        }
-        this.root = root.normalize();
-        Log.info("New symbol source root at \"%s\"", this.root);
-    }
-
-    public SymbolSolverQuickSetup(Path root, DirFilter dirFilter) {
-        this(root);
-        this.dirFilter = dirFilter;
-    }
-
-    public TypeSolver walk() throws IOException {
-        Files.walkFileTree(root, new JavaSymbolSolverWalker());
-        Files.walkFileTree(root, new JarVisitor());
-        return typeSolver;
-    }
-
-    public Optional<TypeSolver> tryToWalk() {
-        try {
-            return Optional.of(walk());
-        } catch (IOException e) {
-            Log.error(e, "Unable to walk root " + root);
-            return Optional.empty();
-        }
-    }
-
-    public TypeSolver getTypeSolver() {
-        return typeSolver;
-    }
-
-    /**
-     * The path that was passed in the constructor.
-     */
-    public Path getRoot() {
-        return root;
-    }
-
-    /**
-     * Walks the directory and adds the roots of the java files to the TypeSolver
-     */
-    private class JavaSymbolSolverWalker extends SimpleFileVisitor<Path> {
-
-        private final Set<Path> roots = new HashSet<>();
-
-        @Override
-        public FileVisitResult visitFile(Path file, BasicFileAttributes attr) throws FileNotFoundException {
-            if (attr.isRegularFile()) {
-                PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.java");
-                if (matcher.matches(file)) {
-                    try {
-                        Optional<Path> root = JavaParser.parse(file.toFile()).getStorage()
-                                .map(CompilationUnit.Storage::getSourceRoot);
-                        if (root.isPresent()) {
-                            typeSolver.add(new JavaParserTypeSolver(root.get().toFile()));
-                            if (roots.add(root.get())) {
-                                Log.trace("Added dir " + root.get() + " to the TypeSolver");
-                                return SKIP_SIBLINGS;
-                            }
-                        }
-                    } catch (ParseProblemException e) {
-                        Log.error(e, "Unable to parse file " + file);
-                    }
-                }
-            }
-            return CONTINUE;
-        }
-
-        @Override
-        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
-            if (Files.isHidden(dir) || dirFilter.filter(dir) || roots.stream().anyMatch(dir::startsWith)) {
-                return SKIP_SUBTREE;
-            }
-            return CONTINUE;
-        }
-    }
-
-    private class JarVisitor extends SimpleFileVisitor<Path> {
-
-        @Override
-        public FileVisitResult visitFile(Path file, BasicFileAttributes attr) throws IOException {
-            if (attr.isRegularFile()) {
-                PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.jar");
-                if (matcher.matches(file)) {
-                    typeSolver.add(new JarTypeSolver(file.toString()));
-                }
-            }
-            return CONTINUE;
-        }
-    }
-}
-
diff --git a/javaparser-symbol-solver-logic/javaparser-symbol-solver-logic.iml b/javaparser-symbol-solver-logic/javaparser-symbol-solver-logic.iml
deleted file mode 100644
index 2a2531a..0000000
--- a/javaparser-symbol-solver-logic/javaparser-symbol-solver-logic.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="Maven: org.javassist:javassist:3.22.0-GA" level="project" />
-    <orderEntry type="module" module-name="javaparser-symbol-solver-model" />
-    <orderEntry type="module" module-name="javaparser-core" />
-    <orderEntry type="library" name="Maven: com.google.guava:guava:23.4-jre" level="project" />
-    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
-    <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.0.18" level="project" />
-    <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.1" level="project" />
-    <orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14" level="project" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-symbol-solver-logic/pom.xml b/javaparser-symbol-solver-logic/pom.xml
index 25b7856..7fc71ba 100644
--- a/javaparser-symbol-solver-logic/pom.xml
+++ b/javaparser-symbol-solver-logic/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>javaparser-parent</artifactId>
         <groupId>com.github.javaparser</groupId>
-        <version>3.5.16-SNAPSHOT</version>
+        <version>3.14.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -48,61 +48,6 @@
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>animal-sniffer-maven-plugin</artifactId>
-                <version>1.16</version>
-                <configuration>
-                    <signature>
-                        <!-- Make sure only the API of this JDK is used -->
-                        <groupId>org.codehaus.mojo.signature</groupId>
-                        <artifactId>java18</artifactId>
-                        <version>1.0</version>
-                    </signature>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>animal-sniffer</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>check</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-enforcer-plugin</artifactId>
-                <version>3.0.0-M1</version>
-                <executions>
-                    <execution>
-                        <id>enforce-versions</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>enforce</goal>
-                        </goals>
-                        <configuration>
-                            <rules>
-                                <requireJavaVersion>
-                                    <!-- Make sure a compiler of this version is used -->
-                                    <version>${java.version}</version>
-                                </requireJavaVersion>
-                                <enforceBytecodeVersion>
-                                    <!-- Make sure the dependencies are compiled for our Java version -->
-                                    <maxJdkVersion>${java.version}</maxJdkVersion>
-                                </enforceBytecodeVersion>
-                            </rules>
-                        </configuration>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>extra-enforcer-rules</artifactId>
-                        <version>1.0-beta-6</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
             <!-- Set JPMS module name -->
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
diff --git a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration.java b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration.java
index 1f770e7..0db1ab6 100644
--- a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration.java
+++ b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration.java
@@ -27,7 +27,8 @@
  *
  * @author Federico Tomassetti
  */
-public abstract class AbstractClassDeclaration extends AbstractTypeDeclaration implements ResolvedClassDeclaration {
+public abstract class AbstractClassDeclaration extends AbstractTypeDeclaration
+        implements ResolvedClassDeclaration, MethodResolutionCapability {
 
     ///
     /// Public
diff --git a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java
index b08ff1e..e69c06e 100644
--- a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java
+++ b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java
@@ -22,7 +22,6 @@
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 /**
diff --git a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic.java b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic.java
index 94ce18b..c5df1d4 100644
--- a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic.java
+++ b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic.java
@@ -68,6 +68,9 @@
     }
 
     public static boolean isFunctionalInterfaceType(ResolvedType type) {
+        if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().hasAnnotation(FunctionalInterface.class.getCanonicalName())) {
+            return true;
+        }
         return getFunctionalMethod(type).isPresent();
     }
 
diff --git a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/InferenceContext.java b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/InferenceContext.java
index 4d3df0f..a4dd5f1 100644
--- a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/InferenceContext.java
+++ b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/InferenceContext.java
@@ -18,7 +18,6 @@
 
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.types.*;
-import com.github.javaparser.symbolsolver.model.typesystem.*;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -34,13 +33,12 @@
     private int nextInferenceVariableId = 0;
     private ObjectProvider objectProvider;
     private List<InferenceVariableType> inferenceVariableTypes = new ArrayList<>();
+    private Map<String, InferenceVariableType> inferenceVariableTypeMap = new HashMap<>();
 
     public InferenceContext(ObjectProvider objectProvider) {
         this.objectProvider = objectProvider;
     }
 
-    private Map<String, InferenceVariableType> inferenceVariableTypeMap = new HashMap<>();
-
     private InferenceVariableType inferenceVariableTypeForTp(ResolvedTypeParameterDeclaration tp) {
         if (!inferenceVariableTypeMap.containsKey(tp.getName())) {
             InferenceVariableType inferenceVariableType = new InferenceVariableType(nextInferenceVariableId++, objectProvider);
@@ -52,7 +50,6 @@
     }
 
     /**
-     *
      * @return the actual with the inference variable inserted
      */
     public ResolvedType addPair(ResolvedType target, ResolvedType actual) {
@@ -79,7 +76,7 @@
                     ancestors = formalTypeAsReference.getAllAncestors();
                     final String actualParamTypeQname = actualTypeAsReference.getQualifiedName();
                     List<ResolvedType> correspondingActualType = ancestors.stream().filter(a -> a.getQualifiedName().equals(actualParamTypeQname)).collect(Collectors.toList());
-                    if (correspondingActualType.isEmpty()){
+                    if (correspondingActualType.isEmpty()) {
                         throw new ConfilictingGenericTypesException(formalType, actualType);
                     }
                     correspondingFormalType = correspondingActualType;
@@ -132,20 +129,20 @@
                 }
             }
 
-            if (actualType.isReferenceType()){
-                if (formalType.asWildcard().isBounded()){
+            if (actualType.isReferenceType()) {
+                if (formalType.asWildcard().isBounded()) {
                     registerCorrespondance(formalType.asWildcard().getBoundedType(), actualType);
                 }
             }
-        } else if (actualType instanceof InferenceVariableType){
-            if (formalType instanceof ResolvedReferenceType){
+        } else if (actualType instanceof InferenceVariableType) {
+            if (formalType instanceof ResolvedReferenceType) {
                 ((InferenceVariableType) actualType).registerEquivalentType(formalType);
-            } else if (formalType instanceof InferenceVariableType){
+            } else if (formalType instanceof InferenceVariableType) {
                 ((InferenceVariableType) actualType).registerEquivalentType(formalType);
             }
-        } else if (actualType.isConstraint()){
+        } else if (actualType.isConstraint()) {
             ResolvedLambdaConstraintType constraintType = actualType.asConstraintType();
-            if (constraintType.getBound() instanceof InferenceVariableType){
+            if (constraintType.getBound() instanceof InferenceVariableType) {
                 ((InferenceVariableType) constraintType.getBound()).registerEquivalentType(formalType);
             }
         } else if (actualType.isPrimitive()) {
@@ -154,6 +151,16 @@
             } else {
                 registerCorrespondance(formalType, objectProvider.byName(actualType.asPrimitive().getBoxTypeQName()));
             }
+        } else if (actualType.isReferenceType()) {
+            if (formalType.isPrimitive()) {
+                if (formalType.asPrimitive().getBoxTypeQName().equals(actualType.describe())) {
+                    registerCorrespondance(objectProvider.byName(formalType.asPrimitive().getBoxTypeQName()), actualType);
+                } else {
+                    // nothing to do
+                }
+            } else {
+                // nothing to do
+            }
         } else {
             throw new UnsupportedOperationException(formalType.describe() + " " + actualType.describe());
         }
@@ -176,7 +183,7 @@
             return new ResolvedArrayType(placeInferenceVariables(type.asArrayType().getComponentType()));
         } else if (type.isNull() || type.isPrimitive() || type.isVoid()) {
             return type;
-        } else if (type.isConstraint()){
+        } else if (type.isConstraint()) {
             return ResolvedLambdaConstraintType.bound(placeInferenceVariables(type.asConstraintType().getBound()));
         } else if (type instanceof InferenceVariableType) {
             return type;
diff --git a/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/MethodResolutionCapability.java b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/MethodResolutionCapability.java
new file mode 100644
index 0000000..8190572
--- /dev/null
+++ b/javaparser-symbol-solver-logic/src/main/java/com/github/javaparser/symbolsolver/logic/MethodResolutionCapability.java
@@ -0,0 +1,12 @@
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+
+import java.util.List;
+
+public interface MethodResolutionCapability {
+	SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes,
+	                                                       boolean staticOnly);
+}
diff --git a/javaparser-symbol-solver-model/.gitignore b/javaparser-symbol-solver-model/.gitignore
index 2c773c9..50d10e2 100644
--- a/javaparser-symbol-solver-model/.gitignore
+++ b/javaparser-symbol-solver-model/.gitignore
@@ -11,7 +11,6 @@
 # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
 hs_err_pid*
 .idea
-*.iml
 target
 build
 /.classpath
diff --git a/javaparser-symbol-solver-model/pom.xml b/javaparser-symbol-solver-model/pom.xml
index fd824e3..0e8cd35 100644
--- a/javaparser-symbol-solver-model/pom.xml
+++ b/javaparser-symbol-solver-model/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>javaparser-parent</artifactId>
         <groupId>com.github.javaparser</groupId>
-        <version>3.5.16-SNAPSHOT</version>
+        <version>3.14.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -48,59 +48,6 @@
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>animal-sniffer-maven-plugin</artifactId>
-                <configuration>
-                    <signature>
-                        <!-- Make sure only the API of this JDK is used -->
-                        <groupId>org.codehaus.mojo.signature</groupId>
-                        <artifactId>java18</artifactId>
-                        <version>1.0</version>
-                    </signature>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>animal-sniffer</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>check</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-enforcer-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>enforce-versions</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>enforce</goal>
-                        </goals>
-                        <configuration>
-                            <rules>
-                                <requireJavaVersion>
-                                    <!-- Make sure a compiler of this version is used -->
-                                    <version>${java.version}</version>
-                                </requireJavaVersion>
-                                <enforceBytecodeVersion>
-                                    <!-- Make sure the dependencies are compiled for our Java version -->
-                                    <maxJdkVersion>${java.version}</maxJdkVersion>
-                                </enforceBytecodeVersion>
-                            </rules>
-                        </configuration>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>extra-enforcer-rules</artifactId>
-                        <version>1.0-beta-6</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
             <!-- Set JPMS module name -->
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
diff --git a/javaparser-symbol-solver-model/src/main/java/com/github/javaparser/symbolsolver/model/resolution/TypeSolver.java b/javaparser-symbol-solver-model/src/main/java/com/github/javaparser/symbolsolver/model/resolution/TypeSolver.java
index bfa43ae..43533b0 100644
--- a/javaparser-symbol-solver-model/src/main/java/com/github/javaparser/symbolsolver/model/resolution/TypeSolver.java
+++ b/javaparser-symbol-solver-model/src/main/java/com/github/javaparser/symbolsolver/model/resolution/TypeSolver.java
@@ -18,7 +18,6 @@
 
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import com.github.javaparser.resolution.types.ResolvedType;
 
 /**
  * An element able to find TypeDeclaration from their name.
@@ -67,4 +66,7 @@
         }
     }
 
+    default boolean hasType(String name) {
+        return tryToSolveType(name).isSolved();
+    }
 }
diff --git a/javaparser-symbol-solver-testing/javaparser-symbol-solver-testing.iml b/javaparser-symbol-solver-testing/javaparser-symbol-solver-testing.iml
deleted file mode 100644
index bf53f2c..0000000
--- a/javaparser-symbol-solver-testing/javaparser-symbol-solver-testing.iml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
-    <orderEntry type="module" module-name="javaparser-symbol-solver-logic" />
-    <orderEntry type="library" name="Maven: org.javassist:javassist:3.22.0-GA" level="project" />
-    <orderEntry type="library" name="Maven: com.google.guava:guava:23.4-jre" level="project" />
-    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
-    <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.0.18" level="project" />
-    <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.1" level="project" />
-    <orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:2.13.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.7.9" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.7.9" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
-    <orderEntry type="module" module-name="javaparser-symbol-solver-model" />
-    <orderEntry type="module" module-name="javaparser-core" />
-    <orderEntry type="module" module-name="javaparser-symbol-solver-core" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/pom.xml b/javaparser-symbol-solver-testing/pom.xml
index 6e042d2..600afcd 100644
--- a/javaparser-symbol-solver-testing/pom.xml
+++ b/javaparser-symbol-solver-testing/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>javaparser-parent</artifactId>
         <groupId>com.github.javaparser</groupId>
-        <version>3.5.16-SNAPSHOT</version>
+        <version>3.14.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -47,18 +47,6 @@
         </profile>
         <profile>
             <id>AlsoSlowTests</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <parallel>methods</parallel>
-                            <threadCount>4</threadCount>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
         </profile>
     </profiles>
 
@@ -108,93 +96,6 @@
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>unpack-test-jss-sources</id>
-                        <phase>test-compile</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>com.github.javaparser</groupId>
-                                    <artifactId>java-symbol-solver-core</artifactId>
-                                    <version>0.6.0</version>
-                                    <classifier>sources</classifier>
-                                    <outputDirectory>
-                                        ${project.build.directory}/test-classes/javasymbolsolver_0_6_0/src/java-symbol-solver-core
-                                    </outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>com.github.javaparser</groupId>
-                                    <artifactId>java-symbol-solver-logic</artifactId>
-                                    <version>0.6.0</version>
-                                    <classifier>sources</classifier>
-                                    <outputDirectory>
-                                        ${project.build.directory}/test-classes/javasymbolsolver_0_6_0/src/java-symbol-solver-logic
-                                    </outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>com.github.javaparser</groupId>
-                                    <artifactId>java-symbol-solver-model</artifactId>
-                                    <version>0.6.0</version>
-                                    <classifier>sources</classifier>
-                                    <outputDirectory>
-                                        ${project.build.directory}/test-classes/javasymbolsolver_0_6_0/src/java-symbol-solver-model
-                                    </outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>copy-test-jss-libs</id>
-                        <phase>test-compile</phase>
-                        <goals>
-                            <goal>copy</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>com.google.guava</groupId>
-                                    <artifactId>guava</artifactId>
-                                    <version>21.0</version>
-                                    <outputDirectory>
-                                        ${project.build.directory}/test-classes/javasymbolsolver_0_6_0/lib
-                                    </outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>com.github.javaparser</groupId>
-                                    <artifactId>javaparser-core</artifactId>
-                                    <version>3.5.10</version>
-                                    <outputDirectory>
-                                        ${project.build.directory}/test-classes/javasymbolsolver_0_6_0/lib
-                                    </outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>io.javaslang</groupId>
-                                    <artifactId>javaslang</artifactId>
-                                    <version>2.0.3</version>
-                                    <outputDirectory>
-                                        ${project.build.directory}/test-classes/javasymbolsolver_0_6_0/lib
-                                    </outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.javassist</groupId>
-                                    <artifactId>javassist</artifactId>
-                                    <version>3.19.0-GA</version>
-                                    <outputDirectory>
-                                        ${project.build.directory}/test-classes/javasymbolsolver_0_6_0/lib
-                                    </outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-deploy-plugin</artifactId>
                 <configuration>
                     <!-- no need to release this module -->
@@ -205,8 +106,20 @@
     </build>
     <dependencies>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.junit-pioneer</groupId>
+            <artifactId>junit-pioneer</artifactId>
         </dependency>
         <dependency>
             <groupId>com.github.javaparser</groupId>
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/SlowTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/SlowTest.java
index db79147..b0afb9d 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/SlowTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/SlowTest.java
@@ -1,7 +1,13 @@
 package com.github.javaparser;
 
-/**
- * Test category marker.
- */
-public interface SlowTest {
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.junit.jupiter.api.Tag;
+
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Tag("com.github.javaparser.SlowTest")
+public @interface SlowTest {
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/resolution/types/ResolvedPrimitiveTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/resolution/types/ResolvedPrimitiveTypeTest.java
deleted file mode 100644
index 494b2b2..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/resolution/types/ResolvedPrimitiveTypeTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.resolution.types;
-
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class ResolvedPrimitiveTypeTest extends AbstractResolutionTest {
-
-    private String exampleOfSwitch(ResolvedPrimitiveType rpt) {
-        switch (rpt) {
-            case INT:
-                return "I";
-            case BYTE:
-                return "B";
-            case DOUBLE:
-                return "D";
-            default:
-                return "U";
-        }
-    }
-
-    @Test
-    public void tryTheSwitchStatement() {
-        assertEquals("U", exampleOfSwitch(ResolvedPrimitiveType.BOOLEAN));
-        assertEquals("U", exampleOfSwitch(ResolvedPrimitiveType.CHAR));
-        assertEquals("B", exampleOfSwitch(ResolvedPrimitiveType.BYTE));
-        assertEquals("U", exampleOfSwitch(ResolvedPrimitiveType.SHORT));
-        assertEquals("I", exampleOfSwitch(ResolvedPrimitiveType.INT));
-        assertEquals("U", exampleOfSwitch(ResolvedPrimitiveType.LONG));
-        assertEquals("U", exampleOfSwitch(ResolvedPrimitiveType.FLOAT));
-        assertEquals("D", exampleOfSwitch(ResolvedPrimitiveType.DOUBLE));
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/AbstractSymbolResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/AbstractSymbolResolutionTest.java
new file mode 100644
index 0000000..aa85afd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/AbstractSymbolResolutionTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.utils.CodeGenerationUtils;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public abstract class AbstractSymbolResolutionTest {
+
+    protected static Path adaptPath(Path path) {
+        if (Files.exists(path)) {
+            return path.toAbsolutePath();
+        }
+        Path underSymbolSolver = CodeGenerationUtils.mavenModuleRoot(AbstractSymbolResolutionTest.class).resolve("javaparser-symbol-solver-testing").resolve(path);
+        if (Files.exists(underSymbolSolver)) {
+            return underSymbolSolver;
+        } else {
+            throw new IllegalArgumentException("I cannot adapt the path " + path);
+        }
+    }
+
+    protected static Path adaptPath(String path) {
+        return adaptPath(Paths.get(path));
+    }
+
+    protected boolean isJavaVersion9OrAbove() {
+        String jdkVersion = System.getProperty("java.version");
+        return Integer.parseInt(jdkVersion.substring(0, jdkVersion.indexOf('.'))) >= 9;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/AbstractTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/AbstractTest.java
deleted file mode 100644
index 911211b..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/AbstractTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver;
-
-import java.io.File;
-
-public abstract class AbstractTest {
-
-    protected static File adaptPath(File path) {
-        if (path.exists()) {
-            return path;
-        } else {
-            File underJavaParserCore = new File("javaparser-symbol-solver-testing/" + path.getPath());
-            if (underJavaParserCore.exists()) {
-                return underJavaParserCore;
-            } else {
-                throw new IllegalArgumentException("I cannot adapt the path " + path.getAbsolutePath());
-            }
-        }
-    }
-
-    protected static String adaptPath(String path) {
-        return adaptPath(new File(path)).getPath();
-    }
-
-    protected boolean isJava9() {
-        return System.getProperty("java.version").startsWith("9.");
-    }
-
-    protected boolean isJava8() {
-        return System.getProperty("java.version").startsWith("1.8.");
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/FindingAllFields.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/FindingAllFields.java
deleted file mode 100644
index c0b70e9..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/FindingAllFields.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Test;
-
-import java.util.stream.Collectors;
-
-import static org.junit.Assert.assertEquals;
-
-public class FindingAllFields extends AbstractResolutionTest {
-
-    @Test
-    public void findAllInheritedFields() {
-        CompilationUnit cu = parseSample("AClassWithFields");
-        ClassOrInterfaceDeclaration classC = Navigator.demandClass(cu, "C");
-        ResolvedReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(new ReflectionTypeSolver()).getTypeDeclaration(classC);
-        assertEquals(3, typeDeclaration.getAllFields().size());
-        assertEquals(ImmutableSet.of("a", "b", "c"),
-                typeDeclaration.getAllFields().stream().map(ResolvedDeclaration::getName).collect(Collectors.toSet()));
-    }
-
-    @Test
-    public void findAllInheritedFieldsAndGenerics() {
-        CompilationUnit cu = parseSample("AClassWithFieldsAndGenerics");
-        ClassOrInterfaceDeclaration classC = Navigator.demandClass(cu, "C");
-        ResolvedReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(new ReflectionTypeSolver()).getTypeDeclaration(classC);
-        assertEquals(3, typeDeclaration.getAllFields().size());
-        assertEquals(ImmutableSet.of("a", "b", "c"),
-                typeDeclaration.getAllFields().stream().map(ResolvedDeclaration::getName).collect(Collectors.toSet()));
-        assertEquals("java.util.List<java.lang.String>", typeDeclaration.getField("b").getType().describe());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/FindingAllFieldsTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/FindingAllFieldsTest.java
new file mode 100644
index 0000000..4d1d0fb
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/FindingAllFieldsTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.google.common.collect.ImmutableSet;
+import org.junit.jupiter.api.Test;
+
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class FindingAllFieldsTest extends AbstractResolutionTest {
+
+    @Test
+    void findAllInheritedFields() {
+        CompilationUnit cu = parseSample("AClassWithFields");
+        ClassOrInterfaceDeclaration classC = Navigator.demandClass(cu, "C");
+        ResolvedReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(new ReflectionTypeSolver()).getTypeDeclaration(classC);
+        assertEquals(3, typeDeclaration.getAllFields().size());
+        assertEquals(ImmutableSet.of("a", "b", "c"),
+                typeDeclaration.getAllFields().stream().map(ResolvedDeclaration::getName).collect(Collectors.toSet()));
+    }
+
+    @Test
+    void findAllInheritedFieldsAndGenerics() {
+        CompilationUnit cu = parseSample("AClassWithFieldsAndGenerics");
+        ClassOrInterfaceDeclaration classC = Navigator.demandClass(cu, "C");
+        ResolvedReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(new ReflectionTypeSolver()).getTypeDeclaration(classC);
+        assertEquals(3, typeDeclaration.getAllFields().size());
+        assertEquals(ImmutableSet.of("a", "b", "c"),
+                typeDeclaration.getAllFields().stream().map(ResolvedDeclaration::getName).collect(Collectors.toSet()));
+        assertEquals("java.util.List<java.lang.String>", typeDeclaration.getField("b").getType().describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue113.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue113.java
deleted file mode 100644
index e57a2e1..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue113.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.resolution.types.ResolvedReferenceType;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue113 extends AbstractTest {
-
-    private TypeSolver typeSolver;
-
-    @Before
-    public void setup() throws IOException {
-        typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(adaptPath(new File("src/test/resources/issue113"))));
-    }
-
-    @Test
-    public void issue113providedCodeDoesNotCrash() throws FileNotFoundException {
-        String pathToSourceFile = adaptPath("src/test/resources/issue113/com/foo/Widget.java");
-        CompilationUnit cu = JavaParser.parse(new File(pathToSourceFile));
-
-        JavaParserFacade parserFacade = JavaParserFacade.get(typeSolver);
-        MethodDeclaration methodDeclaration = cu.findAll(MethodDeclaration.class).stream()
-                .filter(node -> node.getName().getIdentifier().equals("doSomething")).findAny().orElse(null);
-        methodDeclaration.findAll(MethodCallExpr.class).forEach(parserFacade::solve);
-    }
-
-    @Test
-    public void issue113superClassIsResolvedCorrectly() throws FileNotFoundException {
-        String pathToSourceFile = adaptPath("src/test/resources/issue113/com/foo/Widget.java");
-        CompilationUnit cu = JavaParser.parse(new File(pathToSourceFile));
-
-        JavaParserClassDeclaration jssExtendedWidget = new JavaParserClassDeclaration(cu.getClassByName("Widget").get(), typeSolver);
-        ResolvedReferenceType superClass = jssExtendedWidget.getSuperClass();
-        assertEquals("com.foo.base.Widget", superClass.getQualifiedName());
-    }
-
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue113Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue113Test.java
new file mode 100644
index 0000000..aedb219
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue113Test.java
@@ -0,0 +1,53 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue113Test extends AbstractSymbolResolutionTest {
+
+    private TypeSolver typeSolver;
+
+    @BeforeEach
+    void setup() {
+        typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(adaptPath("src/test/resources/issue113"), new LeanParserConfiguration()));
+    }
+
+    @Test
+    void issue113providedCodeDoesNotCrash() throws IOException {
+        Path pathToSourceFile = adaptPath("src/test/resources/issue113/com/foo/Widget.java");
+        CompilationUnit cu = parse(pathToSourceFile);
+
+        JavaParserFacade parserFacade = JavaParserFacade.get(typeSolver);
+        MethodDeclaration methodDeclaration = cu.findAll(MethodDeclaration.class).stream()
+                .filter(node -> node.getName().getIdentifier().equals("doSomething")).findAny().orElse(null);
+        methodDeclaration.findAll(MethodCallExpr.class).forEach(parserFacade::solve);
+    }
+
+    @Test
+    void issue113superClassIsResolvedCorrectly() throws IOException {
+        Path pathToSourceFile = adaptPath("src/test/resources/issue113/com/foo/Widget.java");
+        CompilationUnit cu = parse(pathToSourceFile);
+
+        JavaParserClassDeclaration jssExtendedWidget = new JavaParserClassDeclaration(cu.getClassByName("Widget").get(), typeSolver);
+        ResolvedReferenceType superClass = jssExtendedWidget.getSuperClass();
+        assertEquals("com.foo.base.Widget", superClass.getQualifiedName());
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue116.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue116.java
deleted file mode 100644
index d8d346d..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue116.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue116 extends AbstractResolutionTest {
-
-    @Test
-    public void arrayTypeIsNotPartOfTheTree() {
-        CompilationUnit cu = parseSample("Issue116");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
-        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "foo");
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        com.github.javaparser.ast.type.Type typeNode = methodDeclaration.getParameters().get(0).getType();
-        ResolvedType type = javaParserFacade.convert(typeNode, typeNode);
-        assertEquals("java.lang.String[]", type.describe());
-
-        ExpressionStmt expressionStmt = (ExpressionStmt) methodDeclaration.getBody().get().getStatements().get(0);
-        Expression argRef = expressionStmt.getExpression();
-        assertEquals("java.lang.String[]", javaParserFacade.getType(argRef).describe());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue116Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue116Test.java
new file mode 100644
index 0000000..e334720
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue116Test.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue116Test extends AbstractResolutionTest {
+
+    @Test
+    void arrayTypeIsNotPartOfTheTree() {
+        CompilationUnit cu = parseSample("Issue116");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
+        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "foo");
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        com.github.javaparser.ast.type.Type typeNode = methodDeclaration.getParameters().get(0).getType();
+        ResolvedType type = javaParserFacade.convert(typeNode, typeNode);
+        assertEquals("java.lang.String[]", type.describe());
+
+        ExpressionStmt expressionStmt = (ExpressionStmt) methodDeclaration.getBody().get().getStatements().get(0);
+        Expression argRef = expressionStmt.getExpression();
+        assertEquals("java.lang.String[]", javaParserFacade.getType(argRef).describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue128.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue128.java
deleted file mode 100644
index 38f8b7c..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue128.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue128 extends AbstractResolutionTest {
-
-    private TypeSolver typeSolver;
-
-    @Before
-    public void setup() throws IOException {
-        File srcDir = adaptPath(new File("src/test/resources/issue128"));
-        typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(srcDir));
-    }
-
-    @Test
-    public void verifyJavaTestClassIsSolved() {
-        typeSolver.solveType("foo.JavaTest");
-    }
-
-    @Test
-    public void loopOnStaticallyImportedType() {
-        CompilationUnit cu = parseSampleWithStandardExtension("issue128/foo/Issue128");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
-        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("test").get(0).getBody().get().getStatement(0);
-        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-
-        assertEquals(false, javaParserFacade.solve(methodCallExpr).isSolved());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue128Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue128Test.java
new file mode 100644
index 0000000..8a650f3
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue128Test.java
@@ -0,0 +1,48 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue128Test extends AbstractResolutionTest {
+
+    private TypeSolver typeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path srcDir = adaptPath("src/test/resources/issue128");
+        typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(srcDir, new LeanParserConfiguration()));
+    }
+
+    @Test
+    void verifyJavaTestClassIsSolved() {
+        typeSolver.solveType("foo.JavaTest");
+    }
+
+    @Test
+    void loopOnStaticallyImportedType() {
+        CompilationUnit cu = parseSampleWithStandardExtension("issue128/foo/Issue128");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
+        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("test").get(0).getBody().get().getStatement(0);
+        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+
+        assertEquals(false, javaParserFacade.solve(methodCallExpr).isSolved());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1364.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1364.java
deleted file mode 100644
index 67086b0..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1364.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParseStart;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.Providers;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.expr.SimpleName;
-import com.github.javaparser.resolution.UnsolvedSymbolException;
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
-import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
-import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-/**
- * @author Dominik Hardtke
- * @since 02.02.2018
- */
-public class Issue1364 extends AbstractResolutionTest {
-    private JavaParser javaParser;
-
-    @Before
-    public void setup() {
-        ClassOrInterfaceDeclaration fakeObject = new ClassOrInterfaceDeclaration();
-        fakeObject.setName(new SimpleName("java.lang.Object"));
-
-        TypeSolver typeSolver = new TypeSolver() {
-            @Override
-            public TypeSolver getParent() {
-                return null;
-            }
-
-            @Override
-            public void setParent(TypeSolver parent) {
-            }
-
-            @Override
-            public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name) {
-                if ("java.lang.Object".equals(name)) {
-                    // custom handling
-                    return SymbolReference.solved(new JavaParserClassDeclaration(fakeObject, this));
-                }
-
-                return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
-            }
-        };
-
-        ParserConfiguration config = new ParserConfiguration();
-        config.setSymbolResolver(new JavaSymbolSolver(typeSolver));
-        javaParser = new JavaParser(config);
-    }
-
-    @Test(timeout = 1000)
-    public void resolveSubClassOfObject() {
-        String code = String.join(System.lineSeparator(),
-                "package graph;",
-                "public class Vertex {",
-                "    public static void main(String[] args) {",
-                "        System.out.println();",
-                "    }",
-                "}"
-        );
-
-        ParseResult<CompilationUnit> parseResult = javaParser.parse(ParseStart.COMPILATION_UNIT, Providers.provider(code));
-        assertTrue(parseResult.isSuccessful());
-        assertTrue(parseResult.getResult().isPresent());
-
-        List<MethodCallExpr> methodCallExprs = parseResult.getResult().get().findAll(MethodCallExpr.class);
-        assertEquals(1, methodCallExprs.size());
-
-        try {
-            methodCallExprs.get(0).calculateResolvedType();
-            fail("An UnsolvedSymbolException should be thrown");
-        } catch (UnsolvedSymbolException ignored) {
-            // all is fine if an UnsolvedSymbolException is thrown
-        }
-    }
-}
-
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1364Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1364Test.java
new file mode 100644
index 0000000..6ed1b06
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1364Test.java
@@ -0,0 +1,87 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.Providers;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import java.time.Duration;
+import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
+
+/**
+ * @author Dominik Hardtke
+ * @since 02/02/2018
+ */
+class Issue1364Test extends AbstractResolutionTest {
+    private JavaParser javaParser;
+
+    @BeforeEach
+    void setup() {
+        ClassOrInterfaceDeclaration fakeObject = new ClassOrInterfaceDeclaration();
+        fakeObject.setName(new SimpleName("java.lang.Object"));
+
+        TypeSolver typeSolver = new TypeSolver() {
+            @Override
+            public TypeSolver getParent() {
+                return null;
+            }
+
+            @Override
+            public void setParent(TypeSolver parent) {
+            }
+
+            @Override
+            public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name) {
+                if ("java.lang.Object".equals(name)) {
+                    // custom handling
+                    return SymbolReference.solved(new JavaParserClassDeclaration(fakeObject, this));
+                }
+
+                return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
+            }
+        };
+
+        ParserConfiguration config = new ParserConfiguration();
+        config.setSymbolResolver(new JavaSymbolSolver(typeSolver));
+        javaParser = new JavaParser(config);
+    }
+
+    @Test
+    void resolveSubClassOfObject() {
+        assertTimeoutPreemptively(Duration.ofMillis(1000L), () -> {
+            String code = String.join(System.lineSeparator(), "package graph;", "public class Vertex {", "    public static void main(String[] args) {", "        System.out.println();", "    }", "}");
+        ParseResult<CompilationUnit> parseResult = javaParser.parse(ParseStart.COMPILATION_UNIT, Providers.provider(code));
+        assertTrue(parseResult.isSuccessful());
+        assertTrue(parseResult.getResult().isPresent());
+        List<MethodCallExpr> methodCallExprs = parseResult.getResult().get().findAll(MethodCallExpr.class);
+        assertEquals(1, methodCallExprs.size());
+        try {
+            methodCallExprs.get(0).calculateResolvedType();
+        fail("An UnsolvedSymbolException should be thrown");
+    } catch (UnsolvedSymbolException ignored) {
+    }
+    });
+
+                        
+                
+}
+}
+
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue144.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue144.java
deleted file mode 100644
index 74c8ff7..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue144.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.resolution.UnsolvedSymbolException;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue144 extends AbstractResolutionTest {
-
-    private TypeSolver typeSolver;
-
-    @Before
-    public void setup() throws IOException {
-        File srcDir = adaptPath(new File("src/test/resources/issue144"));
-        typeSolver = new JavaParserTypeSolver(srcDir);
-    }
-
-    @Test(expected = UnsolvedSymbolException.class)
-    public void issue144() {
-        CompilationUnit cu = parseSampleWithStandardExtension("issue144/HelloWorld");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "HelloWorld");
-        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("main").get(0).getBody().get().getStatement(0);
-        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
-        Expression firstParameter = methodCallExpr.getArgument(0);
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-
-        javaParserFacade.solve(firstParameter).isSolved();
-    }
-
-    @Test
-    public void issue144WithReflectionTypeSolver() {
-        CompilationUnit cu = parseSampleWithStandardExtension("issue144/HelloWorld");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "HelloWorld");
-        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("main").get(0).getBody().get().getStatement(0);
-        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
-        Expression firstParameter = methodCallExpr.getArgument(0);
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(new ReflectionTypeSolver(true));
-
-        assertEquals(true, javaParserFacade.solve(firstParameter).isSolved());
-    }
-
-    @Test
-    public void issue144WithCombinedTypeSolver() {
-        CompilationUnit cu = parseSampleWithStandardExtension("issue144/HelloWorld");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "HelloWorld");
-        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("main").get(0).getBody().get().getStatement(0);
-        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
-        Expression firstParameter = methodCallExpr.getArgument(0);
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(new CombinedTypeSolver(typeSolver, new ReflectionTypeSolver(true)));
-
-        assertEquals(true, javaParserFacade.solve(firstParameter).isSolved());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue144Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue144Test.java
new file mode 100644
index 0000000..28fd6bf
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue144Test.java
@@ -0,0 +1,70 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue144Test extends AbstractResolutionTest {
+
+    private TypeSolver typeSolver;
+
+    @BeforeEach
+    void setup() {
+        Path srcDir = adaptPath("src/test/resources/issue144");
+        typeSolver = new JavaParserTypeSolver(srcDir, new LeanParserConfiguration());
+    }
+
+    @Test
+    void issue144() {
+        CompilationUnit cu = parseSampleWithStandardExtension("issue144/HelloWorld");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "HelloWorld");
+        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("main").get(0).getBody().get().getStatement(0);
+        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
+        Expression firstParameter = methodCallExpr.getArgument(0);
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+
+        assertEquals(true, javaParserFacade.solve(firstParameter).isSolved());
+        assertEquals(true, javaParserFacade.solve(firstParameter).getCorrespondingDeclaration().isField());
+        assertEquals("hw", javaParserFacade.solve(firstParameter).getCorrespondingDeclaration().getName());
+    }
+
+    @Test
+    void issue144WithReflectionTypeSolver() {
+        CompilationUnit cu = parseSampleWithStandardExtension("issue144/HelloWorld");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "HelloWorld");
+        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("main").get(0).getBody().get().getStatement(0);
+        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
+        Expression firstParameter = methodCallExpr.getArgument(0);
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(new ReflectionTypeSolver(true));
+
+        assertEquals(true, javaParserFacade.solve(firstParameter).isSolved());
+    }
+
+    @Test
+    void issue144WithCombinedTypeSolver() {
+        CompilationUnit cu = parseSampleWithStandardExtension("issue144/HelloWorld");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "HelloWorld");
+        ExpressionStmt expressionStmt = (ExpressionStmt)clazz.getMethodsByName("main").get(0).getBody().get().getStatement(0);
+        MethodCallExpr methodCallExpr = (MethodCallExpr) expressionStmt.getExpression();
+        Expression firstParameter = methodCallExpr.getArgument(0);
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(new CombinedTypeSolver(typeSolver, new ReflectionTypeSolver(true)));
+
+        assertEquals(true, javaParserFacade.solve(firstParameter).isSolved());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1485Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1485Test.java
new file mode 100644
index 0000000..2383011
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1485Test.java
@@ -0,0 +1,42 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.StreamProvider;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue1485Test extends AbstractSymbolResolutionTest {
+
+    @Test
+    void issue1485withoutSpecifyingJARs() throws IOException {
+        Path dir = adaptPath("src/test/resources/issue1485");
+        Path file = adaptPath("src/test/resources/issue1485/Complex.java");
+
+        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
+        typeSolver.add(new ReflectionTypeSolver());
+        typeSolver.add(new JavaParserTypeSolver(dir, new LeanParserConfiguration()));
+
+        JavaParser javaParser = new JavaParser();
+        javaParser.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
+
+        CompilationUnit unit = javaParser.parse(ParseStart.COMPILATION_UNIT,
+                new StreamProvider(Files.newInputStream(file))).getResult().get();
+
+        MethodCallExpr methodCallExpr = unit.findFirst(MethodCallExpr.class, m -> m.getName().getIdentifier().equals("println")).get();
+        ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
+        assertEquals("java.io.PrintStream.println(java.lang.String)", resolvedMethodDeclaration.getQualifiedSignature());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1491Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1491Test.java
new file mode 100644
index 0000000..7b853f6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1491Test.java
@@ -0,0 +1,105 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+
+class Issue1491Test {
+
+    @Test
+    void verifyIssue1491SolvingClassInSameFile() throws FileNotFoundException {
+        File aJava = new File("src/test/resources/issue1491/A.java");
+        if (!aJava.exists()) {
+            throw new IllegalStateException();
+        }
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(aJava.getAbsoluteFile().getParentFile()));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        StaticJavaParser.setConfiguration(parserConfiguration);
+
+        CompilationUnit cu = parse(aJava);
+        cu.accept(new VoidVisitorAdapter() {
+            public void visit(NameExpr n, Object arg) {
+                ResolvedType type = JavaParserFacade.get(localCts)
+                        .getType(n);
+                super.visit(n, arg);
+            }
+        }, null);
+    }
+
+    @Test
+    void verifyIssue1491ResolvingStaticMethodCalls() throws FileNotFoundException {
+        File aJava = new File("src/test/resources/issue1491/A.java");
+        if (!aJava.exists()) {
+            throw new IllegalStateException();
+        }
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(aJava.getAbsoluteFile().getParentFile()));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        StaticJavaParser.setConfiguration(parserConfiguration);
+
+        CompilationUnit cu = parse(aJava);
+        cu.accept(new VoidVisitorAdapter() {
+
+            public void visit(MethodCallExpr n, Object arg) {
+                ResolvedMethodDeclaration decl = JavaParserFacade.get(localCts).solve(n).getCorrespondingDeclaration();
+                super.visit(n, arg);
+            }
+        }, null);
+    }
+
+    @Test
+    void verifyIssue1491Combined() throws FileNotFoundException {
+        File aJava = new File("src/test/resources/issue1491/A.java");
+        if (!aJava.exists()) {
+            throw new IllegalStateException();
+        }
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(aJava.getAbsoluteFile().getParentFile()));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        StaticJavaParser.setConfiguration(parserConfiguration);
+
+        CompilationUnit cu = parse(aJava);
+        cu.accept(new VoidVisitorAdapter<Void>() {
+            public void visit(NameExpr n, Void arg) {
+                try {
+                    ResolvedType type = JavaParserFacade.get(localCts).getType(n);
+                } catch (UnsolvedSymbolException e) {
+                    throw new RuntimeException("Unable to solve name expr at " + n.getRange(), e);
+                }
+                super.visit(n, arg);
+            }
+
+            public void visit(MethodCallExpr n, Void arg) {
+                ResolvedMethodDeclaration decl = JavaParserFacade.get(localCts).solve(n).getCorrespondingDeclaration();
+                super.visit(n, arg);
+            }
+        }, null);
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue156.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue156.java
deleted file mode 100644
index b500af7..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue156.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue156 extends AbstractResolutionTest {
-
-    @Test
-    public void testFieldAccessThroughClassAndThis() {
-
-        CompilationUnit cu = parseSample("Issue156");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Issue156");
-        List<MethodCallExpr> methods = clazz.getChildNodes().get(2).getChildNodes().get(1).findAll(MethodCallExpr.class);
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-
-        assertEquals("char", javaParserFacade.getType(methods.get(0)).describe());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue156Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue156Test.java
new file mode 100644
index 0000000..7eadab9
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue156Test.java
@@ -0,0 +1,30 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue156Test extends AbstractResolutionTest {
+
+    @Test
+    void testFieldAccessThroughClassAndThis() {
+
+        CompilationUnit cu = parseSample("Issue156");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Issue156");
+          List<MethodCallExpr> methods = clazz.getChildNodes().get(3).getChildNodes().get(1).findAll(MethodCallExpr.class);
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+
+        assertEquals("char", javaParserFacade.getType(methods.get(0)).describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1668Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1668Test.java
new file mode 100644
index 0000000..102ae4d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1668Test.java
@@ -0,0 +1,53 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class Issue1668Test {
+
+    private JavaParser javaParser;
+
+    @BeforeEach
+    void setUp() {
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        ParserConfiguration config = new ParserConfiguration();
+        config.setSymbolResolver(new JavaSymbolSolver(typeSolver));
+        javaParser = new JavaParser(config);
+    }
+
+    @Test
+    void testResolveArrayDeclaration() {
+        String code = String.join(System.lineSeparator(),
+                "public class X {",
+                "   public static void main(String[] args) {",
+                "       String s = \"a,b,c,d,e\";",
+                "       String[] stringArray = s.split(',');",
+                "   }",
+                "}"
+        );
+
+        ParseResult<CompilationUnit> parseResult = javaParser.parse(ParseStart.COMPILATION_UNIT, Providers.provider(code));
+        assertTrue(parseResult.isSuccessful());
+        assertTrue(parseResult.getResult().isPresent());
+
+        CompilationUnit compilationUnit = parseResult.getResult().get();
+        VariableDeclarator variableDeclarator = compilationUnit.findFirst(VariableDeclarator.class, v ->
+                v.getNameAsString().equals("stringArray")).get();
+        VariableDeclarationExpr variableDeclarationExpr = (VariableDeclarationExpr) variableDeclarator.getParentNode().get();
+        ResolvedType resolvedType = variableDeclarationExpr.calculateResolvedType();
+        assertEquals("java.lang.String[]", resolvedType.describe());
+        ResolvedValueDeclaration resolve = variableDeclarator.resolve();
+        assertEquals("java.lang.String[]", resolve.getType().describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue18.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue18.java
deleted file mode 100644
index af0dd18..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue18.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue18 extends AbstractResolutionTest {
-
-    @Test
-    public void typeDeclarationSuperClassImplicitlyIncludeObject() {
-        CompilationUnit cu = parseSample("Issue18");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
-        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "bar");
-        ExpressionStmt expr = (ExpressionStmt) methodDeclaration.getBody().get().getStatements().get(1);
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        ResolvedType type = javaParserFacade.getType(expr.getExpression());
-        assertEquals("java.lang.Object", type.describe());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1814Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1814Test.java
new file mode 100644
index 0000000..39b10ea
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1814Test.java
@@ -0,0 +1,86 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.time.Duration;
+import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
+
+/**
+ * @author Dominik Hardtke
+ * @since 01/09/2018
+ */
+class Issue1814Test extends AbstractResolutionTest {
+    private JavaParser javaParser;
+
+    @BeforeEach
+    void setup() {
+        final CompilationUnit compilationUnit = new CompilationUnit();
+        compilationUnit.setPackageDeclaration("java.lang");
+        // construct a fake java.lang.Object class with only one method (java.lang.Object#equals(java.lang.Object)
+        final ClassOrInterfaceDeclaration clazz = compilationUnit.addClass("Object", Modifier.Keyword.PUBLIC);
+        final MethodDeclaration equals = clazz.addMethod("equals", Modifier.Keyword.PUBLIC);
+        equals.addParameter("Object", "obj");
+        final BlockStmt body = new BlockStmt();
+        body.addStatement("return this == obj;");
+        equals.setBody(body);
+
+        TypeSolver typeSolver = new TypeSolver() {
+            @Override
+            public TypeSolver getParent() {
+                return null;
+            }
+
+            @Override
+            public void setParent(TypeSolver parent) {
+            }
+
+            @Override
+            public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name) {
+                if ("java.lang.Object".equals(name)) {
+                    // custom handling
+                    return SymbolReference.solved(new JavaParserClassDeclaration(clazz, this));
+                }
+
+                return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
+            }
+        };
+
+        ParserConfiguration config = new ParserConfiguration();
+        config.setSymbolResolver(new JavaSymbolSolver(typeSolver));
+        javaParser = new JavaParser(config);
+    }
+
+    @Test
+    void getAllMethodsVisibleToInheritors() {
+        assertTimeoutPreemptively(Duration.ofMillis(1000L), () -> {
+            String code = String.join(System.lineSeparator(), "public class AbstractExercise extends java.lang.Object {", "}");
+            ParseResult<CompilationUnit> parseResult = javaParser.parse(ParseStart.COMPILATION_UNIT, Providers.provider(code));
+            assertTrue(parseResult.isSuccessful());
+            assertTrue(parseResult.getResult().isPresent());
+            List<ClassOrInterfaceType> referenceTypes = parseResult.getResult().get().findAll(ClassOrInterfaceType.class);
+            assertTrue(referenceTypes.size() > 0);
+            final List<ResolvedMethodDeclaration> methods = referenceTypes.get(0).resolve().getAllMethodsVisibleToInheritors();
+            assertEquals(1, methods.size());
+        });
+
+
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue185.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue185.java
deleted file mode 100644
index c0ad0b1..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue185.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertNotNull;
-
-
-public class Issue185 extends AbstractResolutionTest {
-
-    @Test
-    public void testIssue() throws FileNotFoundException {
-        File src = adaptPath(new File("src/test/resources/recursion-issue"));
-        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
-        combinedTypeSolver.add(new JavaParserTypeSolver(src));
-        combinedTypeSolver.add(new ReflectionTypeSolver());
-        CompilationUnit agendaCu = JavaParser.parse(adaptPath(new File("src/test/resources/recursion-issue/Usage.java")));
-        MethodCallExpr foo = Navigator.findMethodCall(agendaCu, "foo").get();
-        assertNotNull(foo);
-        JavaParserFacade.get(combinedTypeSolver).getType(foo);
-    }
-
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue185Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue185Test.java
new file mode 100644
index 0000000..5f355f0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue185Test.java
@@ -0,0 +1,35 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+
+class Issue185Test extends AbstractResolutionTest {
+
+    @Test
+    void testIssue() throws IOException {
+        Path src = adaptPath("src/test/resources/recursion-issue");
+        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
+        combinedTypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+        combinedTypeSolver.add(new ReflectionTypeSolver());
+        CompilationUnit agendaCu = parse(adaptPath("src/test/resources/recursion-issue/Usage.java"));
+        MethodCallExpr foo = Navigator.findMethodCall(agendaCu, "foo").get();
+        assertNotNull(foo);
+        JavaParserFacade.get(combinedTypeSolver).getType(foo);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue186.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue186.java
deleted file mode 100644
index 2590e9e..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue186.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.LambdaExpr;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue186 extends AbstractResolutionTest {
-
-    @Test
-    public void lambdaFlatMapIssue() {
-        CompilationUnit cu = parseSample("Issue186");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
-        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "foo");
-        MethodCallExpr methodCallExpr = Navigator.findMethodCall(methodDeclaration, "flatMap").get();
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        assertEquals("java.util.stream.Stream<java.lang.String>", javaParserFacade.getType(methodCallExpr).describe());
-
-    }
-
-    @Test
-    public void lambdaPrimitivesIssue() {
-        CompilationUnit cu = parseSample("Issue186");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
-        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "bar");
-        List<LambdaExpr> lambdas = methodDeclaration.findAll(LambdaExpr.class);
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        assertEquals("java.util.function.Predicate<? super java.lang.String>", javaParserFacade.getType(lambdas.get(0)).describe());
-        assertEquals("java.util.function.Function<? super java.lang.String, ? extends java.lang.Integer>", javaParserFacade.getType(lambdas.get(1)).describe());
-        assertEquals("java.util.function.Predicate<? super java.lang.Integer>", javaParserFacade.getType(lambdas.get(2)).describe());
-
-    }
-
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue186Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue186Test.java
new file mode 100644
index 0000000..2cbf334
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue186Test.java
@@ -0,0 +1,47 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.LambdaExpr;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue186Test extends AbstractResolutionTest {
+
+    @Test
+    void lambdaFlatMapIssue() {
+        CompilationUnit cu = parseSample("Issue186");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
+        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "foo");
+        MethodCallExpr methodCallExpr = Navigator.findMethodCall(methodDeclaration, "flatMap").get();
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        assertEquals("java.util.stream.Stream<java.lang.String>", javaParserFacade.getType(methodCallExpr).describe());
+
+    }
+
+    @Test
+    void lambdaPrimitivesIssue() {
+        CompilationUnit cu = parseSample("Issue186");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
+        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "bar");
+        List<LambdaExpr> lambdas = methodDeclaration.findAll(LambdaExpr.class);
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        assertEquals("java.util.function.Predicate<? super java.lang.String>", javaParserFacade.getType(lambdas.get(0)).describe());
+        assertEquals("java.util.function.Function<? super java.lang.String, ? extends java.lang.Integer>", javaParserFacade.getType(lambdas.get(1)).describe());
+        assertEquals("java.util.function.Predicate<? super java.lang.Integer>", javaParserFacade.getType(lambdas.get(2)).describe());
+
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue18Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue18Test.java
new file mode 100644
index 0000000..9e04b72
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue18Test.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue18Test extends AbstractResolutionTest {
+
+    @Test
+    void typeDeclarationSuperClassImplicitlyIncludeObject() {
+        CompilationUnit cu = parseSample("Issue18");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
+        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "bar");
+        ExpressionStmt expr = (ExpressionStmt) methodDeclaration.getBody().get().getStatements().get(1);
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        ResolvedType type = javaParserFacade.getType(expr.getExpression());
+        assertEquals("java.lang.Object", type.describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1946Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1946Test.java
new file mode 100644
index 0000000..67b9faf
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue1946Test.java
@@ -0,0 +1,40 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.StringProvider;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue1946Test {
+
+
+    @Test
+    void issueWithInternalEnumConstantReference() {
+        String code = "package com.github.javaparser.symbolsolver.testingclasses; class Foo { void foo() { UtilityClass.method(SomeClass.InnerEnum.CONSTANT); } }";
+        JavaParser jp = new JavaParser();
+        CombinedTypeSolver typeSolver = new CombinedTypeSolver(new TypeSolver[] {
+                new ReflectionTypeSolver(false)
+        });
+        jp.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
+        ParseResult<CompilationUnit> pr = jp.parse(ParseStart.COMPILATION_UNIT, new StringProvider(code));
+        assertEquals(true, pr.isSuccessful());
+        MethodCallExpr methodCallExpr = pr.getResult().get().findFirst(MethodCallExpr.class).get();
+        ResolvedMethodDeclaration rmd = methodCallExpr.resolve();
+        assertEquals("com.github.javaparser.symbolsolver.testingclasses.UtilityClass.method(com.github.javaparser.symbolsolver.testingclasses.SomeClass.InnerEnum)", rmd.getQualifiedSignature());
+        FieldAccessExpr fieldAccessExpr = methodCallExpr.findFirst(FieldAccessExpr.class).get();
+        ResolvedValueDeclaration rvd = fieldAccessExpr.resolve();
+        assertEquals("CONSTANT", rvd.getName());
+        assertEquals("com.github.javaparser.symbolsolver.testingclasses.SomeClass.InnerEnum", rvd.getType().describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue200.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue200.java
deleted file mode 100644
index ff35987..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue200.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.ast.stmt.ReturnStmt;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue200 extends AbstractResolutionTest {
-
-    @Test
-    public void issue200() {
-        CompilationUnit cu = parseSample("Issue200");
-        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
-        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "foo");
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        List<ReturnStmt> nodesByType = methodDeclaration.findAll(ReturnStmt.class);
-        assertEquals("java.util.stream.Stream<JavaTest.Solved>", javaParserFacade.getType((nodesByType.get(0)).getExpression().get()).describe());
-    }
-}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue200Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue200Test.java
new file mode 100644
index 0000000..0b89119
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue200Test.java
@@ -0,0 +1,30 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue200Test extends AbstractResolutionTest {
+
+    @Test
+    void issue200() {
+        CompilationUnit cu = parseSample("Issue200");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "JavaTest");
+        MethodDeclaration methodDeclaration = Navigator.demandMethod(clazz, "foo");
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        List<ReturnStmt> nodesByType = methodDeclaration.findAll(ReturnStmt.class);
+        assertEquals("java.util.stream.Stream<JavaTest.Solved>", javaParserFacade.getType((nodesByType.get(0)).getExpression().get()).describe());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2035Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2035Test.java
new file mode 100644
index 0000000..f0330a1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2035Test.java
@@ -0,0 +1,158 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.github.javaparser.Providers.provider;
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
+
+class Issue2035Test {
+
+    private JavaParser javaParser;
+
+    @BeforeEach
+    void setUp() {
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver());
+        ParserConfiguration configuration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
+
+        javaParser = new JavaParser(configuration);
+    }
+
+    @Test
+    void test() {
+        String x = "" +
+                "class X {\n" +
+                "    \n" +
+                "    private void a(int a){ }\n" +
+                "    private void b(Integer a){ }\n" +
+                "    \n" +
+                "    private void c(){\n" +
+                "        int x=0;\n" +
+                "        Integer y=0;\n" +
+                "        \n" +
+                "        a(x);\n" +
+                "        a(y);\n" +
+                "        \n" +
+                "        b(x);\n" +
+                "        b(y);\n" +
+                "        \n" +
+                "    }\n" +
+                "}" +
+                "";
+
+        ParseResult<CompilationUnit> parseResult = javaParser.parse(
+                ParseStart.COMPILATION_UNIT,
+                provider(x)
+        );
+
+        parseResult.getResult().ifPresent(compilationUnit -> {
+            final List<MethodCallExpr> matches = compilationUnit
+                    .findAll(MethodCallExpr.class);
+
+            assumeFalse(matches.isEmpty(), "Cannot attempt resolving types if no matches.");
+            matches.forEach(methodCallExpr -> {
+                try {
+                    methodCallExpr.resolve().getReturnType();
+                    methodCallExpr.calculateResolvedType(); //
+                } catch (UnsupportedOperationException e) {
+                    Assertions.fail("Resolution failed.", e);
+                }
+            });
+        });
+
+    }
+
+
+    @Test
+    void test_int() {
+        String x_int = "" +
+                "import java.util.*;\n" +
+                "\n" +
+                "class X {\n" +
+                "    \n" +
+                "    private void a(){\n" +
+                "        ArrayList<String> abc = new ArrayList<>();\n" +
+                "        int x = 0; \n" +
+                "        abc.get(x);\n" +
+                "    }\n" +
+                "}" +
+                "";
+
+        ParseResult<CompilationUnit> parseResult = javaParser.parse(
+                ParseStart.COMPILATION_UNIT,
+                provider(x_int)
+        );
+
+        parseResult.getResult().ifPresent(compilationUnit -> {
+            final List<MethodCallExpr> matches = compilationUnit
+                    .findAll(MethodCallExpr.class)
+                    .stream()
+                    .filter(methodCallExpr -> methodCallExpr.getNameAsString().equals("get"))
+                    .collect(Collectors.toList());
+
+            assumeFalse(matches.isEmpty(), "Cannot attempt resolving types if no matches.");
+            matches.forEach(methodCallExpr -> {
+                try {
+                    methodCallExpr.resolve().getReturnType();
+                    methodCallExpr.calculateResolvedType();
+                } catch (UnsupportedOperationException e) {
+                    Assertions.fail("Resolution failed.", e);
+                }
+            });
+        });
+
+    }
+
+    @Test
+    void test_Integer() {
+        String x_Integer = "" +
+                "import java.util.*;\n" +
+                "\n" +
+                "class X {\n" +
+                "    \n" +
+                "    private void a(){\n" +
+                "        ArrayList<String> abc = new ArrayList<>();\n" +
+                "        Integer x = 0; \n" +
+                "        abc.get(x);\n" +
+                "    }\n" +
+                "}" +
+                "";
+
+        ParseResult<CompilationUnit> parseResult = javaParser.parse(
+                ParseStart.COMPILATION_UNIT,
+                provider(x_Integer)
+        );
+
+        parseResult.getResult().ifPresent(compilationUnit -> {
+            final List<MethodCallExpr> matches = compilationUnit
+                    .findAll(MethodCallExpr.class)
+                    .stream()
+                    .filter(methodCallExpr -> methodCallExpr.getNameAsString().equals("get"))
+                    .collect(Collectors.toList());
+
+            assumeFalse(matches.isEmpty(), "Cannot attempt resolving types if no matches.");
+            matches.forEach(methodCallExpr -> {
+                try {
+                    methodCallExpr.resolve().getReturnType();
+                    methodCallExpr.calculateResolvedType();
+                } catch (UnsupportedOperationException e) {
+                    Assertions.fail("Resolution failed.", e);
+                }
+            });
+        });
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue228.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue228.java
deleted file mode 100644
index 7ed5bdb..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue228.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.resolution.MethodUsage;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-public class Issue228 extends AbstractResolutionTest{
-
-    @Test
-    public void testSolvingMethodWitPrimitiveParameterTypeAsUsage() {
-        String code = 
-                  "class Test { "
-                + "  long l = call(1); "
-                + "  long call(final long i) { "
-                + "    return i; "
-                + "  }"
-                + "}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodCallExpr methodCall = cu.findAll(MethodCallExpr.class).get(0);
-        JavaParserFacade parserFacade = JavaParserFacade.get(new ReflectionTypeSolver());
-        MethodUsage solvedCall = parserFacade.solveMethodAsUsage(methodCall);
-        assertEquals("long", solvedCall.getParamType(0).describe());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue228Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue228Test.java
new file mode 100644
index 0000000..c9042f6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue228Test.java
@@ -0,0 +1,31 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue228Test extends AbstractResolutionTest{
+
+    @Test
+    void testSolvingMethodWitPrimitiveParameterTypeAsUsage() {
+        String code = 
+                  "class Test { "
+                + "  long l = call(1); "
+                + "  long call(final long i) { "
+                + "    return i; "
+                + "  }"
+                + "}";
+        CompilationUnit cu = parse(code);
+        MethodCallExpr methodCall = cu.findAll(MethodCallExpr.class).get(0);
+        JavaParserFacade parserFacade = JavaParserFacade.get(new ReflectionTypeSolver());
+        MethodUsage solvedCall = parserFacade.solveMethodAsUsage(methodCall);
+        assertEquals("long", solvedCall.getParamType(0).describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue232.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue232.java
deleted file mode 100644
index cb4550d..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue232.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
-import com.github.javaparser.symbolsolver.core.resolution.Context;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
-import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-public class Issue232 extends AbstractResolutionTest {
-    @Test
-    public void issue232() {
-        CompilationUnit cu = parseSample("Issue232");
-        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "OfDouble");
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        Context context = JavaParserFactory.getContext(cls, typeSolver);
-        SymbolReference<ResolvedTypeDeclaration> reference = context.solveType("OfPrimitive<Double, DoubleConsumer, OfDouble>", typeSolver);
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue232Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue232Test.java
new file mode 100644
index 0000000..f9bbe71
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue232Test.java
@@ -0,0 +1,26 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+class Issue232Test extends AbstractResolutionTest {
+    @Test
+    void issue232() {
+        CompilationUnit cu = parseSample("Issue232");
+        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "OfDouble");
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        Context context = JavaParserFactory.getContext(cls, typeSolver);
+        SymbolReference<ResolvedTypeDeclaration> reference = context.solveType("OfPrimitive<Double, DoubleConsumer, OfDouble>");
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue235.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue235.java
deleted file mode 100644
index 0e4d1aa..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue235.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.ObjectCreationExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-@RunWith(Parameterized.class)
-public class Issue235 extends AbstractResolutionTest{
-    private final String method;
-
-    public Issue235(String method) {
-        this.method = method;
-    }
-
-    @Parameterized.Parameters(name = "{0}")
-    public static Collection<String> data() throws Exception {
-        return Arrays.asList(
-                "new_Bar_Baz_direct",
-                "new_Bar_Baz",
-                "new_Bar",
-                "new_Foo_Bar"
-        );
-    }
-
-    @Test
-    public void issue235() {
-        CompilationUnit cu = parseSample("Issue235");
-        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "Foo");
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        MethodDeclaration m = Navigator.demandMethod(cls, this.method);
-        ExpressionStmt stmt = (ExpressionStmt) m.getBody().get().getStatements().get(0);
-        ObjectCreationExpr expression = (ObjectCreationExpr) stmt.getExpression();
-        Assert.assertNotNull(javaParserFacade.convertToUsage(expression.getType()));
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue235Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue235Test.java
new file mode 100644
index 0000000..e9f038e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue235Test.java
@@ -0,0 +1,43 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+class Issue235Test extends AbstractResolutionTest{
+
+    static Collection<String> data() {
+        return Arrays.asList(
+                "new_Bar_Baz_direct",
+                "new_Bar_Baz",
+                "new_Bar",
+                "new_Foo_Bar"
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("data")
+    void issue235(String method) {
+        CompilationUnit cu = parseSample("Issue235");
+        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "Foo");
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        MethodDeclaration m = Navigator.demandMethod(cls, method);
+        ExpressionStmt stmt = (ExpressionStmt) m.getBody().get().getStatements().get(0);
+        ObjectCreationExpr expression = (ObjectCreationExpr) stmt.getExpression();
+        Assertions.assertNotNull(javaParserFacade.convertToUsage(expression.getType()));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue241.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue241.java
deleted file mode 100644
index 9b42314..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue241.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.type.Type;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-import java.io.File;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue241 extends AbstractResolutionTest{
-
-    @Test
-    public void testSolveStaticallyImportedMemberType() {
-        File src = adaptPath(new File("src/test/resources"));
-        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(src));
-        		
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        
-        CompilationUnit cu = parseSample("Issue241");
-        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "Main");
-        VariableDeclarator v = Navigator.demandVariableDeclaration(cls, "foo").get();
-        
-        Type t = v.getType();
-        ResolvedType t2 = javaParserFacade.convert(t, t);
-        String typeName = t2.asReferenceType().getQualifiedName();
-       
-        assertEquals("issue241.TypeWithMemberType.MemberInterface", typeName);
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue241Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue241Test.java
new file mode 100644
index 0000000..fbfa182
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue241Test.java
@@ -0,0 +1,41 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.type.Type;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
+
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue241Test extends AbstractResolutionTest{
+
+    @Test
+    void testSolveStaticallyImportedMemberType() {
+        Path src = adaptPath("src/test/resources");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+        		
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        
+        CompilationUnit cu = parseSample("Issue241");
+        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "Main");
+        VariableDeclarator v = Navigator.demandVariableDeclaration(cls, "foo").get();
+        
+        Type t = v.getType();
+        ResolvedType t2 = javaParserFacade.convert(t, t);
+        String typeName = t2.asReferenceType().getQualifiedName();
+       
+        assertEquals("issue241.TypeWithMemberType.MemberInterface", typeName);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue251.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue251.java
deleted file mode 100644
index d8dc0a7..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue251.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class Issue251 extends AbstractResolutionTest{
-
-    @Test
-    public void testSolveStaticallyImportedMemberType() {
-        CompilationUnit cu = parseSample("Issue251");
-        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "Main");
-        TypeSolver typeSolver = new ReflectionTypeSolver();
-        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        MethodDeclaration m = Navigator.demandMethod(cls, "bar");
-        ExpressionStmt stmt = (ExpressionStmt) m.getBody().get().getStatements().get(1);
-        MethodCallExpr expression = (MethodCallExpr) stmt.getExpression();
-        Assert.assertNotNull(javaParserFacade.solve(expression));
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue251Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue251Test.java
new file mode 100644
index 0000000..ce6cb12
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue251Test.java
@@ -0,0 +1,30 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class Issue251Test extends AbstractResolutionTest{
+
+    @Test
+    void testSolveStaticallyImportedMemberType() {
+        CompilationUnit cu = parseSample("Issue251");
+        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "Main");
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        MethodDeclaration m = Navigator.demandMethod(cls, "bar");
+        ExpressionStmt stmt = (ExpressionStmt) m.getBody().get().getStatements().get(1);
+        MethodCallExpr expression = (MethodCallExpr) stmt.getExpression();
+        Assertions.assertNotNull(javaParserFacade.solve(expression));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue276.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue276.java
deleted file mode 100644
index 6baaab0..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue276.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.contexts.MethodContext;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class Issue276 extends AbstractResolutionTest{
-
-    @Test
-    public void testSolveStaticallyImportedMemberType() throws FileNotFoundException {
-        CompilationUnit cu = JavaParser.parse(new File(adaptPath("src/test/resources/issue276/foo/C.java")));
-        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "C");
-        TypeSolver typeSolver = new CombinedTypeSolver(
-        		new ReflectionTypeSolver(), 
-        		new JavaParserTypeSolver(adaptPath(new File("src/test/resources/issue276"))));
-        List<MethodDeclaration> methods = cls.findAll(MethodDeclaration.class);
-        boolean isSolved = false;
-        for (MethodDeclaration method: methods) {
-        	if (method.getNameAsString().equals("overrideMe")) {
-        		MethodContext context = new MethodContext(method, typeSolver);
-        		isSolved = context.solveType("FindMeIfYouCan", typeSolver).isSolved();
-        	}
-        }
-        Assert.assertTrue(isSolved);
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue276Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue276Test.java
new file mode 100644
index 0000000..b4815b3
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue276Test.java
@@ -0,0 +1,41 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.contexts.MethodContext;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.List;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+
+class Issue276Test extends AbstractResolutionTest{
+
+    @Test
+    void testSolveStaticallyImportedMemberType() throws IOException {
+        CompilationUnit cu = parse(adaptPath("src/test/resources/issue276/foo/C.java"));
+        ClassOrInterfaceDeclaration cls = Navigator.demandClassOrInterface(cu, "C");
+        TypeSolver typeSolver = new CombinedTypeSolver(
+        		new ReflectionTypeSolver(), 
+        		new JavaParserTypeSolver(adaptPath("src/test/resources/issue276"), new LeanParserConfiguration()));
+        List<MethodDeclaration> methods = cls.findAll(MethodDeclaration.class);
+        boolean isSolved = false;
+        for (MethodDeclaration method: methods) {
+        	if (method.getNameAsString().equals("overrideMe")) {
+        		MethodContext context = new MethodContext(method, typeSolver);
+        		isSolved = context.solveType("FindMeIfYouCan").isSolved();
+        	}
+        }
+        Assertions.assertTrue(isSolved);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300.java
deleted file mode 100644
index da19b8d..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.FieldAccessExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-import java.io.File;
-import java.io.FileNotFoundException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-public class Issue300 extends AbstractResolutionTest {
-
-    @Test
-    public void fieldAccessIssue() throws ParseException, FileNotFoundException {
-        String pathToSourceFile = adaptPath("src/test/resources/issue300/Issue300.java");
-        CompilationUnit cu = JavaParser.parse(new File(pathToSourceFile));
-
-        final FieldAccessExpr fieldAccess = Navigator.findNodeOfGivenClass(cu, FieldAccessExpr.class);
-        assertNotNull(fieldAccess);
-
-        TypeSolver typeSolver = new CombinedTypeSolver(
-                new ReflectionTypeSolver(),
-                new JavaParserTypeSolver(adaptPath(new File("src/test/resources/issue300"))));
-        final JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
-        final SymbolReference<? extends ResolvedValueDeclaration> ref = javaParserFacade.solve(fieldAccess);
-        assertEquals(ResolvedPrimitiveType.INT, ref.getCorrespondingDeclaration().getType().asPrimitive());
-    }
-}
-
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300Test.java
new file mode 100644
index 0000000..e855507
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300Test.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+class Issue300Test extends AbstractResolutionTest {
+
+    @Test
+    void fieldAccessIssue() throws IOException {
+        Path pathToSourceFile = adaptPath("src/test/resources/issue300/Issue300.java");
+        CompilationUnit cu = parse(pathToSourceFile);
+
+        final FieldAccessExpr fieldAccess = Navigator.findNodeOfGivenClass(cu, FieldAccessExpr.class);
+        assertNotNull(fieldAccess);
+
+        TypeSolver typeSolver = new CombinedTypeSolver(
+                new ReflectionTypeSolver(),
+                new JavaParserTypeSolver(adaptPath("src/test/resources/issue300"), new LeanParserConfiguration()));
+        final JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+        final SymbolReference<? extends ResolvedValueDeclaration> ref = javaParserFacade.solve(fieldAccess);
+        assertEquals(ResolvedPrimitiveType.INT, ref.getCorrespondingDeclaration().getType().asPrimitive());
+    }
+}
+
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue314.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue314.java
deleted file mode 100644
index b20ff79..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue314.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.*;
-import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.FileNotFoundException;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue314 extends AbstractResolutionTest{
-
-    private TypeSolver typeResolver;
-    private JavaParserFacade javaParserFacade;
-
-    private ResolvedType getExpressionType(TypeSolver typeSolver, Expression expression) {
-        return JavaParserFacade.get(typeSolver).getType(expression);
-    }
-
-    @Before
-    public void setup() {
-        typeResolver = new ReflectionTypeSolver();
-        javaParserFacade = JavaParserFacade.get(typeResolver);
-    }
-
-    @Test
-    public void resolveReferenceToFieldInheritedByInterface() {
-        String code = "package foo.bar;\n"+
-                "interface  A {\n" +
-                "        int a = 0;\n" +
-                "    }\n" +
-                "    \n" +
-                "    class B implements A {\n" +
-                "        int getA() {\n" +
-                "            return a;\n" +
-                "        }\n" +
-                "    }";
-        CompilationUnit cu = JavaParser.parse(code);
-        NameExpr refToA = Navigator.findNameExpression(Navigator.demandClass(cu, "B"), "a").get();
-        SymbolReference<? extends ResolvedValueDeclaration> symbolReference = javaParserFacade.solve(refToA);
-        assertEquals(true, symbolReference.isSolved());
-        assertEquals(true, symbolReference.getCorrespondingDeclaration().isField());
-        assertEquals("a", symbolReference.getCorrespondingDeclaration().getName());
-    }
-
-
-
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue314Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue314Test.java
new file mode 100644
index 0000000..1657acd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue314Test.java
@@ -0,0 +1,56 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue314Test extends AbstractResolutionTest{
+
+    private TypeSolver typeResolver;
+    private JavaParserFacade javaParserFacade;
+
+    private ResolvedType getExpressionType(TypeSolver typeSolver, Expression expression) {
+        return JavaParserFacade.get(typeSolver).getType(expression);
+    }
+
+    @BeforeEach
+    void setup() {
+        typeResolver = new ReflectionTypeSolver();
+        javaParserFacade = JavaParserFacade.get(typeResolver);
+    }
+
+    @Test
+    void resolveReferenceToFieldInheritedByInterface() {
+        String code = "package foo.bar;\n"+
+                "interface  A {\n" +
+                "        int a = 0;\n" +
+                "    }\n" +
+                "    \n" +
+                "    class B implements A {\n" +
+                "        int getA() {\n" +
+                "            return a;\n" +
+                "        }\n" +
+                "    }";
+        CompilationUnit cu = parse(code);
+        NameExpr refToA = Navigator.findNameExpression(Navigator.demandClass(cu, "B"), "a").get();
+        SymbolReference<? extends ResolvedValueDeclaration> symbolReference = javaParserFacade.solve(refToA);
+        assertEquals(true, symbolReference.isSolved());
+        assertEquals(true, symbolReference.getCorrespondingDeclaration().isField());
+        assertEquals("a", symbolReference.getCorrespondingDeclaration().getName());
+    }
+
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue343.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue343.java
deleted file mode 100644
index 3c34c6a..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue343.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.expr.*;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue343 extends AbstractResolutionTest{
-
-    private TypeSolver typeResolver;
-    private JavaParserFacade javaParserFacade;
-
-    private ResolvedType getExpressionType(TypeSolver typeSolver, Expression expression) {
-        return JavaParserFacade.get(typeSolver).getType(expression);
-    }
-
-    @Before
-    public void setup() {
-        typeResolver = new ReflectionTypeSolver();
-        javaParserFacade = JavaParserFacade.get(typeResolver);
-    }
-
-    @Test
-    public void resolveStringLiteralOutsideAST() {
-        assertEquals(javaParserFacade.classToResolvedType(String.class), getExpressionType(typeResolver, new StringLiteralExpr("")));
-    }
-
-    @Test
-    public void resolveIntegerLiteralOutsideAST() {
-        assertEquals(javaParserFacade.classToResolvedType(int.class), getExpressionType(typeResolver, new IntegerLiteralExpr(2)));
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void toResolveDoubleWeNeedTheAST() {
-        getExpressionType(typeResolver, JavaParser.parseExpression("new Double[]{2.0d, 3.0d}[1]"));
-    }
-
-
-    @Test(expected = IllegalStateException.class)
-    public void toResolveFloatWeNeedTheAST() {
-        getExpressionType(typeResolver, JavaParser.parseExpression("new Float[]{2.0d, 3.0d}"));
-    }
-
-    @Test
-    public void resolveMethodCallOnStringLiteralOutsideAST() {
-        assertEquals(javaParserFacade.classToResolvedType(int.class), getExpressionType(typeResolver, new MethodCallExpr(new StringLiteralExpr("hello"), "length")));
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void resolveLocaleOutsideAST() {
-        getExpressionType(typeResolver, new FieldAccessExpr(new NameExpr("Locale"), "US"));
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue343Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue343Test.java
new file mode 100644
index 0000000..81b091b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue343Test.java
@@ -0,0 +1,61 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseExpression;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class Issue343Test extends AbstractResolutionTest{
+
+    private TypeSolver typeResolver;
+    private JavaParserFacade javaParserFacade;
+
+    private ResolvedType getExpressionType(TypeSolver typeSolver, Expression expression) {
+        return JavaParserFacade.get(typeSolver).getType(expression);
+    }
+
+    @BeforeEach
+    void setup() {
+        typeResolver = new ReflectionTypeSolver();
+        javaParserFacade = JavaParserFacade.get(typeResolver);
+    }
+
+    @Test
+    void resolveStringLiteralOutsideAST() {
+        assertEquals(javaParserFacade.classToResolvedType(String.class), getExpressionType(typeResolver, new StringLiteralExpr("")));
+    }
+
+    @Test
+    void resolveIntegerLiteralOutsideAST() {
+        assertEquals(javaParserFacade.classToResolvedType(int.class), getExpressionType(typeResolver, new IntegerLiteralExpr(2)));
+    }
+
+    @Test
+    void toResolveDoubleWeNeedTheAST() {
+        assertThrows(IllegalStateException.class, () -> getExpressionType(typeResolver, parseExpression("new Double[]{2.0d, 3.0d}[1]")));
+    }
+
+
+    @Test
+    void toResolveFloatWeNeedTheAST() {
+        assertThrows(IllegalStateException.class, () -> getExpressionType(typeResolver, parseExpression("new Float[]{2.0d, 3.0d}")));
+    }
+
+    @Test
+    void resolveMethodCallOnStringLiteralOutsideAST() {
+        assertEquals(javaParserFacade.classToResolvedType(int.class), getExpressionType(typeResolver, new MethodCallExpr(new StringLiteralExpr("hello"), "length")));
+    }
+
+    @Test
+    void resolveLocaleOutsideAST() {
+        assertThrows(IllegalStateException.class, () -> getExpressionType(typeResolver, new FieldAccessExpr(new NameExpr("Locale"), "US")));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue347.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue347.java
deleted file mode 100644
index 88755be..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue347.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.javaparsermodel.contexts.MethodContext;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue347 extends AbstractResolutionTest{
-
-    private TypeSolver typeSolver;
-    private JavaParserFacade javaParserFacade;
-
-    @Before
-    public void setup() {
-        typeSolver = new ReflectionTypeSolver();
-        javaParserFacade = JavaParserFacade.get(typeSolver);
-    }
-
-    @Test
-    public void resolvingReferenceToEnumDeclarationInSameFile() {
-        String code = "package foo.bar;\nenum Foo {\n" +
-                "    FOO_A, FOO_B\n" +
-                "}\n" +
-                "\n" +
-                "class UsingFoo {\n" +
-                "    Foo myFooField;\n" +
-                "}";
-        CompilationUnit cu = JavaParser.parse(code);
-        FieldDeclaration fieldDeclaration = Navigator.findNodeOfGivenClass(cu, FieldDeclaration.class);
-        ResolvedType fieldType = javaParserFacade.getType(fieldDeclaration);
-        assertEquals(true, fieldType.isReferenceType());
-        assertEquals(true, fieldType.asReferenceType().getTypeDeclaration().isEnum());
-        assertEquals("foo.bar.Foo", fieldType.asReferenceType().getQualifiedName());
-    }
-}
-
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue347Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue347Test.java
new file mode 100644
index 0000000..c0a3c9e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue347Test.java
@@ -0,0 +1,46 @@
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class Issue347Test extends AbstractResolutionTest{
+
+    private TypeSolver typeSolver;
+    private JavaParserFacade javaParserFacade;
+
+    @BeforeEach
+    void setup() {
+        typeSolver = new ReflectionTypeSolver();
+        javaParserFacade = JavaParserFacade.get(typeSolver);
+    }
+
+    @Test
+    void resolvingReferenceToEnumDeclarationInSameFile() {
+        String code = "package foo.bar;\nenum Foo {\n" +
+                "    FOO_A, FOO_B\n" +
+                "}\n" +
+                "\n" +
+                "class UsingFoo {\n" +
+                "    Foo myFooField;\n" +
+                "}";
+        CompilationUnit cu = parse(code);
+        FieldDeclaration fieldDeclaration = Navigator.findNodeOfGivenClass(cu, FieldDeclaration.class);
+        ResolvedType fieldType = javaParserFacade.getType(fieldDeclaration);
+        assertTrue(fieldType.isReferenceType());
+        assertTrue(fieldType.asReferenceType().getTypeDeclaration().isEnum());
+        assertEquals("foo.bar.Foo", fieldType.asReferenceType().getQualifiedName());
+    }
+}
+
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue84.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue84.java
deleted file mode 100644
index ddb920b..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue84.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2016 Federico Tomassetti
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.github.javaparser.symbolsolver;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class Issue84 extends AbstractResolutionTest {
-
-    @Test
-    public void variadicIssue() {
-        CompilationUnit cu = parseSample("Issue84");
-        final MethodCallExpr methodCall = Navigator.findMethodCall(cu, "variadicMethod").get();
-
-        final JavaParserFacade javaParserFacade = JavaParserFacade.get(new ReflectionTypeSolver());
-        final ResolvedType type = javaParserFacade.getType(methodCall);
-        assertEquals(String.class.getCanonicalName(), type.asReferenceType().getQualifiedName());
-    }
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue84Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue84Test.java
new file mode 100644
index 0000000..07816c0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue84Test.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class Issue84Test extends AbstractResolutionTest {
+
+    @Test
+    void variadicIssue() {
+        CompilationUnit cu = parseSample("Issue84");
+        final MethodCallExpr methodCall = Navigator.findMethodCall(cu, "variadicMethod").get();
+
+        final JavaParserFacade javaParserFacade = JavaParserFacade.get(new ReflectionTypeSolver());
+        final ResolvedType type = javaParserFacade.getType(methodCall);
+        assertEquals(String.class.getCanonicalName(), type.asReferenceType().getQualifiedName());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaParserAPIIntegrationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaParserAPIIntegrationTest.java
index eb30722..3b41552 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaParserAPIIntegrationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaParserAPIIntegrationTest.java
@@ -3,7 +3,6 @@
 import com.github.javaparser.JavaParser;
 import com.github.javaparser.ParseStart;
 import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.StreamProvider;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.*;
 import com.github.javaparser.resolution.declarations.*;
@@ -13,30 +12,31 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.List;
 
-import static org.junit.Assert.assertEquals;
+import static com.github.javaparser.Providers.provider;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class JavaParserAPIIntegrationTest extends AbstractTest {
+class JavaParserAPIIntegrationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver;
     private ResolvedReferenceType string;
     private ResolvedReferenceType listOfBoolean;
 
-    @Before
-    public void setup() {
-        File src = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
+    @BeforeEach
+    void setup() {
+        Path src = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
         CombinedTypeSolver combinedTypeSolverNewCode = new CombinedTypeSolver();
         combinedTypeSolverNewCode.add(new ReflectionTypeSolver());
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(src));
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
+        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"), new LeanParserConfiguration()));
         typeSolver = combinedTypeSolverNewCode;
 
         TypeSolver ts = new ReflectionTypeSolver();
@@ -46,8 +46,8 @@
     }
 
     @Test
-    public void annotationDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/resources/Annotations.java.txt"));
+    void annotationDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/resources/Annotations.java.txt");
         CompilationUnit cu = parseWithSymbolResolution(f);
         AnnotationDeclaration declaration = (AnnotationDeclaration)cu.getType(0);
         assertEquals("MyAnnotation", declaration.getNameAsString());
@@ -55,28 +55,28 @@
     }
 
     @Test
-    public void annotationMemberDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/resources/Annotations.java.txt"));
+    void annotationMemberDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/resources/Annotations.java.txt");
         ParserConfiguration parserConfiguration = new ParserConfiguration();
         parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver));
-        CompilationUnit cu = new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT, new StreamProvider(new FileInputStream(f))).getResult().get();
-        AnnotationDeclaration declaration = (AnnotationDeclaration)cu.getType(2);
-        assertEquals("MyAnnotationWithFields", declaration.getNameAsString());
+        CompilationUnit cu = new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT, provider(f)).getResult().get();
+        AnnotationDeclaration declaration = (AnnotationDeclaration)cu.getType(3);
+        assertEquals("MyAnnotationWithElements", declaration.getNameAsString());
         AnnotationMemberDeclaration memberDeclaration = (AnnotationMemberDeclaration)declaration.getMember(0);
         ResolvedAnnotationMemberDeclaration resolvedDeclaration = memberDeclaration.resolve();
     }
 
     @Test
-    public void classDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java"));
+    void classDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java");
         CompilationUnit cu = parseWithSymbolResolution(f);
         ClassOrInterfaceDeclaration declaration = (ClassOrInterfaceDeclaration)cu.getType(0);
         declaration.resolve();
     }
 
     @Test
-    public void interfaceDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/resources/MethodTypeParams.java.txt"));
+    void interfaceDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/resources/MethodTypeParams.java.txt");
         CompilationUnit cu = parseWithSymbolResolution(f);
         ClassOrInterfaceDeclaration declaration = (ClassOrInterfaceDeclaration)cu.getType(1);
         assertEquals("VoidVisitor", declaration.getNameAsString());
@@ -84,23 +84,23 @@
         declaration.resolve();
     }
 
-    private CompilationUnit parseWithSymbolResolution(File f) throws IOException {
+    private CompilationUnit parseWithSymbolResolution(Path f) throws IOException {
         ParserConfiguration parserConfiguration = new ParserConfiguration();
         parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver));
-        return new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT, new StreamProvider(new FileInputStream(f))).getResult().get();
+        return new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT, provider(f)).getResult().get();
     }
 
     @Test
-    public void constructorDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java"));
+    void constructorDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java");
         CompilationUnit cu = parseWithSymbolResolution(f);
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration)cu.getType(0);
         ConstructorDeclaration constructorDeclaration = classOrInterfaceDeclaration.getDefaultConstructor().get();
         ResolvedConstructorDeclaration resolvedConstructorDeclaration = constructorDeclaration.resolve();
     }
     @Test
-    public void enumDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/AccessSpecifier.java"));
+    void enumDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/AccessSpecifier.java");
         CompilationUnit cu = parseWithSymbolResolution(f);
         EnumDeclaration declaration = (EnumDeclaration) cu.getType(0);
         assertEquals("AccessSpecifier", declaration.getNameAsString());
@@ -108,8 +108,8 @@
     }
 
     @Test
-    public void enumConstantDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/AccessSpecifier.java"));
+    void enumConstantDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/AccessSpecifier.java");
         CompilationUnit cu = parseWithSymbolResolution(f);
         EnumDeclaration enumDeclaration = (EnumDeclaration) cu.getType(0);
         assertEquals("AccessSpecifier", enumDeclaration.getNameAsString());
@@ -119,8 +119,8 @@
     }
 
     @Test
-    public void fieldDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java"));
+    void fieldDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java");
         CompilationUnit cu = parseWithSymbolResolution(f);
         ClassOrInterfaceDeclaration classDeclaration = (ClassOrInterfaceDeclaration) cu.getType(0);
         assertEquals("CompilationUnit", classDeclaration.getNameAsString());
@@ -131,8 +131,8 @@
     // TODO make VariableDeclarator resolvable
 
     @Test
-    public void methodDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java"));
+    void methodDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java");
         CompilationUnit cu = parseWithSymbolResolution(f);
         ClassOrInterfaceDeclaration classDeclaration = (ClassOrInterfaceDeclaration) cu.getType(0);
         assertEquals("CompilationUnit", classDeclaration.getNameAsString());
@@ -143,11 +143,11 @@
     }
 
     @Test
-    public void parameterDeclarationResolve() throws IOException {
-        File f = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java"));
+    void parameterDeclarationResolve() throws IOException {
+        Path f = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core/com/github/javaparser/ast/CompilationUnit.java");
         ParserConfiguration parserConfiguration = new ParserConfiguration();
         parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver));
-        CompilationUnit cu = new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT, new StreamProvider(new FileInputStream(f))).getResult().get();
+        CompilationUnit cu = new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT, provider(f)).getResult().get();
         ClassOrInterfaceDeclaration classDeclaration = (ClassOrInterfaceDeclaration) cu.getType(0);
         assertEquals("CompilationUnit", classDeclaration.getNameAsString());
         MethodDeclaration methodDeclaration = classDeclaration.getMethodsByName("setComments").get(0);
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaSymbolSolverTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaSymbolSolverTest.java
index 998a904..80a1c82 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaSymbolSolverTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/JavaSymbolSolverTest.java
@@ -16,30 +16,21 @@
 
 package com.github.javaparser.symbolsolver;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import java.util.stream.Collectors;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import static org.junit.Assert.assertEquals;
-
-public class JavaSymbolSolverTest extends AbstractResolutionTest {
+class JavaSymbolSolverTest extends AbstractResolutionTest {
 
     @Test
-    public void resolveMethodDeclaration() {
+    void resolveMethodDeclaration() {
         TypeSolver typeSolver = new ReflectionTypeSolver();
 
         CompilationUnit cu = parseSample("SymbolResolverExample");
@@ -54,7 +45,7 @@
     }
 
     @Test
-    public void resolveArrayType() {
+    void resolveArrayType() {
         TypeSolver typeSolver = new ReflectionTypeSolver();
 
         CompilationUnit cu = parseSample("SymbolResolverExample");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/SolveMethodDeclaredInEnumTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/SolveMethodDeclaredInEnumTest.java
new file mode 100644
index 0000000..1a0d2e1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/SolveMethodDeclaredInEnumTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.symbolsolver;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StringProvider;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+class SolveMethodDeclaredInEnumTest extends AbstractSymbolResolutionTest {
+
+    @Test
+    void methodDeclaredInEnum_enumFromJar() throws IOException {
+        String code = "public class A { public void callEnum() { MyEnum.CONST.method(); }}";
+        Path jarPath = adaptPath("src/test/resources/solveMethodDeclaredInEnum/MyEnum.jar");
+        TypeSolver typeSolver = new CombinedTypeSolver(new JarTypeSolver(jarPath), new ReflectionTypeSolver());
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(
+                new JavaSymbolSolver(typeSolver));
+        JavaParser javaParser = new JavaParser(parserConfiguration);
+
+        CompilationUnit cu = javaParser.parse(ParseStart.COMPILATION_UNIT, new StringProvider(code)).getResult().get();
+
+        MethodCallExpr call = cu.findFirst(MethodCallExpr.class).orElse(null);
+        ResolvedMethodDeclaration resolvedCall = call.resolve();
+
+        assertNotNull(resolvedCall);
+        assertEquals("MyEnum.method()", resolvedCall.getQualifiedSignature());
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/ConvertToUsageTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/ConvertToUsageTest.java
index 44eda27..488c112 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/ConvertToUsageTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/ConvertToUsageTest.java
@@ -1,24 +1,23 @@
 package com.github.javaparser.symbolsolver.javaparsermodel;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.expr.NameExpr;
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.List;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class ConvertToUsageTest extends AbstractResolutionTest {
+class ConvertToUsageTest extends AbstractResolutionTest {
 
     private final TypeSolver typeSolver = new ReflectionTypeSolver();
 
     @Test
-    public void testConvertTypeToUsage() {
+    void testConvertTypeToUsage() {
         CompilationUnit cu = parseSample("LocalTypeDeclarations");
         List<NameExpr> n = cu.findAll(NameExpr.class);
 
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/DifferentiateDotExpressionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/DifferentiateDotExpressionTest.java
index cf5a87b..359a045 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/DifferentiateDotExpressionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/DifferentiateDotExpressionTest.java
@@ -1,6 +1,5 @@
 package com.github.javaparser.symbolsolver.javaparsermodel;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.MethodCallExpr;
@@ -11,27 +10,26 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import static org.junit.Assert.assertEquals;
-
-public class DifferentiateDotExpressionTest extends AbstractResolutionTest {
+class DifferentiateDotExpressionTest extends AbstractResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
         combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(new File("src/test/resources/differentiate_dot_expressions"))));
+        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath("src/test/resources/differentiate_dot_expressions"), new LeanParserConfiguration()));
         typeSolver = combinedTypeSolver;
     }
 
     @Test
-    public void methodCallsFromFieldObjects() {
+    void methodCallsFromFieldObjects() {
         ClassOrInterfaceDeclaration clazz = ((JavaParserClassDeclaration) typeSolver.solveType("FieldDotExpressions")).getWrappedNode();
         MethodDeclaration mainMethod = Navigator.demandMethod(clazz, "main");
         JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
@@ -46,7 +44,7 @@
     }
 
     @Test
-    public void staticMethodCallsFromInnerClasses() {
+    void staticMethodCallsFromInnerClasses() {
         ClassOrInterfaceDeclaration clazz = ((JavaParserClassDeclaration) typeSolver.solveType("InnerClassDotExpressions")).getWrappedNode();
         MethodDeclaration mainMethod = Navigator.demandMethod(clazz, "main");
         JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
@@ -61,7 +59,7 @@
     }
 
     @Test
-    public void staticFieldCallsFromInnerClasses() {
+    void staticFieldCallsFromInnerClasses() {
         ClassOrInterfaceDeclaration clazz = ((JavaParserClassDeclaration) typeSolver.solveType("InnerStaticClassFieldDotExpressions")).getWrappedNode();
         MethodDeclaration mainMethod = Navigator.demandMethod(clazz, "main");
         JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
@@ -72,7 +70,7 @@
     }
 
     @Test
-    public void packageStaticMethodCalls() {
+    void packageStaticMethodCalls() {
         ClassOrInterfaceDeclaration clazz = ((JavaParserClassDeclaration) typeSolver.solveType("PackageDotExpressions")).getWrappedNode();
         MethodDeclaration mainMethod = Navigator.demandMethod(clazz, "main");
         JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MultiCatchMethodCallExprTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MultiCatchMethodCallExprTest.java
new file mode 100644
index 0000000..f2f87aa
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MultiCatchMethodCallExprTest.java
@@ -0,0 +1,31 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test for issue 1482: https://github.com/javaparser/javaparser/issues/1482
+ * When trying to resolve a MethodCallExpr within a multi catch, an UnsupportedOperationException is thrown.
+ */
+class MultiCatchMethodCallExprTest extends AbstractResolutionTest {
+
+    @Test
+    void issue1482() {
+        CompilationUnit cu = parseSample("Issue1482");
+        cu.accept(new Visitor(), null);
+    }
+
+    private static class Visitor extends VoidVisitorAdapter<Void> {
+        @Override
+        public void visit(MethodCallExpr n, Void arg) {
+            if (n.getArguments().size() != 0) {
+                JavaParserFacade.get(new ReflectionTypeSolver(true)).getType(n.getArgument(0));
+            }
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java
index 1029456..d3370d5 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java
@@ -1,8 +1,8 @@
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
 import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
@@ -13,12 +13,12 @@
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-public class JavaParserAnonymousClassDeclarationTest extends AbstractResolutionTest {
+class JavaParserAnonymousClassDeclarationTest extends AbstractResolutionTest {
 
   @Test
-  public void anonymousClassAsMethodArgument() {
+  void anonymousClassAsMethodArgument() {
     CompilationUnit cu = parseSample("AnonymousClassDeclarations");
     ClassOrInterfaceDeclaration aClass = Navigator.demandClass(cu, "AnonymousClassDeclarations");
     MethodDeclaration method = Navigator.demandMethod(aClass, "fooBar1");
@@ -34,7 +34,7 @@
   }
 
   @Test
-  public void callingSuperClassInnerClassMethod() {
+  void callingSuperClassInnerClassMethod() {
     CompilationUnit cu = parseSample("AnonymousClassDeclarations");
     ClassOrInterfaceDeclaration aClass = Navigator.demandClass(cu, "AnonymousClassDeclarations");
     MethodDeclaration method = Navigator.demandMethod(aClass, "fooBar2");
@@ -50,7 +50,7 @@
   }
 
   @Test
-  public void callingAnonymousClassInnerMethod() {
+  void callingAnonymousClassInnerMethod() {
     CompilationUnit cu = parseSample("AnonymousClassDeclarations");
     ClassOrInterfaceDeclaration aClass = Navigator.demandClass(cu, "AnonymousClassDeclarations");
     MethodDeclaration method = Navigator.demandMethod(aClass, "fooBar3");
@@ -67,7 +67,7 @@
   }
 
   @Test
-  public void usingAnonymousSuperClassInnerType() {
+  void usingAnonymousSuperClassInnerType() {
     CompilationUnit cu = parseSample("AnonymousClassDeclarations");
     ClassOrInterfaceDeclaration aClass = Navigator.demandClass(cu, "AnonymousClassDeclarations");
     MethodDeclaration method = Navigator.demandMethod(aClass, "fooBar4");
@@ -82,7 +82,7 @@
   }
 
   @Test
-  public void usingAnonymousClassInnerType() {
+  void usingAnonymousClassInnerType() {
     CompilationUnit cu = parseSample("AnonymousClassDeclarations");
     ClassOrInterfaceDeclaration aClass = Navigator.demandClass(cu, "AnonymousClassDeclarations");
     MethodDeclaration method = Navigator.demandMethod(aClass, "fooBar5");
@@ -95,4 +95,19 @@
 
     assertThat(methodUsage.getQualifiedSignature(), is("java.lang.Enum.toString()"));
   }
+
+  @Test
+  void callingScopedAnonymousClassInnerMethod() {
+    CompilationUnit cu = parseSample("AnonymousClassDeclarations");
+    ClassOrInterfaceDeclaration aClass = Navigator.demandClass(cu, "AnonymousClassDeclarations");
+    MethodDeclaration method = Navigator.demandMethod(aClass, "fooBar6");
+    MethodCallExpr methodCall = Navigator.findMethodCall(method, "innerClassMethod").get();
+
+    CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
+    combinedTypeSolver.add(new ReflectionTypeSolver());
+    MethodUsage methodUsage =
+            JavaParserFacade.get(combinedTypeSolver).solveMethodAsUsage(methodCall);
+
+    assertThat(methodUsage.getQualifiedSignature(), is("AnonymousClassDeclarations.DoFn.ProcessContext.innerClassMethod()"));
+  }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java
index 0e70b18..5273099 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclarationTest.java
@@ -16,8 +16,6 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.resolution.MethodUsage;
@@ -25,9 +23,10 @@
 import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
@@ -36,40 +35,44 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-import static org.junit.Assert.assertEquals;
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.ast.Modifier.Keyword.PRIVATE;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class JavaParserClassDeclarationTest extends AbstractTest {
+class JavaParserClassDeclarationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver;
     private TypeSolver typeSolverNewCode;
     private ResolvedReferenceType string;
     private ResolvedReferenceType listOfBoolean;
 
-    @Before
-    public void setup() {
-        File src = adaptPath(new File("src/test/test_sourcecode/javaparser_src/proper_source"));
+    @BeforeEach
+    void setup() {
+        Path src = adaptPath("src/test/test_sourcecode/javaparser_src/proper_source");
         CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
         combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(src));
-        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_src/generated"))));
+        combinedTypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_src/generated"), new LeanParserConfiguration()));
         typeSolver = combinedTypeSolver;
 
-        File srcNewCode = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
+        Path srcNewCode = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
         CombinedTypeSolver combinedTypeSolverNewCode = new CombinedTypeSolver();
         combinedTypeSolverNewCode.add(new ReflectionTypeSolver());
         combinedTypeSolverNewCode.add(new JavaParserTypeSolver(srcNewCode));
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
+        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources")));
         typeSolverNewCode = combinedTypeSolverNewCode;
 
         TypeSolver ts = new ReflectionTypeSolver();
@@ -83,73 +86,77 @@
     ///
 
     @Test
-    public void testIsClass() {
+    void testIsClass() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(true, compilationUnit.isClass());
+        assertTrue(compilationUnit.isClass());
     }
 
     @Test
-    public void testIsInterface() {
+    void testIsInterface() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(false, compilationUnit.isInterface());
+        assertFalse(compilationUnit.isInterface());
     }
 
     @Test
-    public void testIsEnum() {
+    void testIsEnum() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(false, compilationUnit.isEnum());
+        assertFalse(compilationUnit.isEnum());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(false, compilationUnit.isTypeParameter());
+        assertFalse(compilationUnit.isTypeParameter());
     }
 
     @Test
-    public void testIsType() {
+    void testIsType() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(true, compilationUnit.isType());
+        assertTrue(compilationUnit.isType());
     }
 
     @Test
-    public void testAsType() {
+    void testAsType() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(compilationUnit, compilationUnit.asType());
     }
 
     @Test
-    public void testAsClass() {
+    void testAsClass() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(compilationUnit, compilationUnit.asClass());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsInterface() {
-        JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
+    @Test
+    void testAsInterface() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         compilationUnit.asInterface();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsEnum() {
-        JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        compilationUnit.asEnum();
-    }
+    });
+}
 
     @Test
-    public void testGetPackageName() {
+    void testAsEnum() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
+        compilationUnit.asEnum();
+    });
+}
+
+    @Test
+    void testGetPackageName() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast", compilationUnit.getPackageName());
     }
 
     @Test
-    public void testGetClassName() {
+    void testGetClassName() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("CompilationUnit", compilationUnit.getClassName());
     }
 
     @Test
-    public void testGetQualifiedName() {
+    void testGetQualifiedName() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast.CompilationUnit", compilationUnit.getQualifiedName());
     }
@@ -159,33 +166,33 @@
     ///
 
     @Test
-    public void testGetSuperclassWithoutTypeParameters() {
+    void testGetSuperclassWithoutTypeParameters() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
     }
 
     @Test
-    public void testGetSuperclassWithTypeParameters() {
+    void testGetSuperclassWithTypeParameters() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", compilationUnit.getSuperClass().getQualifiedName());
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", compilationUnit.getSuperClass().typeParametersMap().getValueBySignature("com.github.javaparser.ast.body.BodyDeclaration.T").get().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void testGetAllSuperclassesWithoutTypeParameters() {
+    void testGetAllSuperclassesWithoutTypeParameters() {
         JavaParserClassDeclaration cu = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllSuperclassesWithTypeParameters() {
+    void testGetAllSuperclassesWithTypeParameters() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(3, constructorDeclaration.getAllSuperClasses().size());
-        assertEquals(true, constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.body.BodyDeclaration")));
-        assertEquals(true, constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.Node")));
-        assertEquals(true, constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("java.lang.Object")));
+        assertTrue(constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.body.BodyDeclaration")));
+        assertTrue(constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.Node")));
+        assertTrue(constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("java.lang.Object")));
 
-        ResolvedReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAllSuperClasses().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -199,7 +206,7 @@
     }
 
     @Test
-    public void testGetInterfacesWithoutParameters() {
+    void testGetInterfacesWithoutParameters() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
 
@@ -208,11 +215,11 @@
     }
 
     @Test
-    public void testGetInterfacesWithParameters() {
+    void testGetInterfacesWithParameters() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(7, constructorDeclaration.getInterfaces().size());
 
-        ResolvedReferenceType interfaze = null;
+        ResolvedReferenceType interfaze;
 
         interfaze = constructorDeclaration.getInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -243,7 +250,7 @@
     }
 
     @Test
-    public void testGetAllInterfacesWithoutParameters() {
+    void testGetAllInterfacesWithoutParameters() {
         JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("java.lang.Cloneable"), compilationUnit.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
 
@@ -252,11 +259,11 @@
     }
 
     @Test
-    public void testGetAllInterfacesWithParameters() {
+    void testGetAllInterfacesWithParameters() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(9, constructorDeclaration.getAllInterfaces().size());
 
-        ResolvedReferenceType interfaze = null;
+        ResolvedReferenceType interfaze;
 
         interfaze = constructorDeclaration.getAllInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -294,11 +301,11 @@
     }
 
     @Test
-    public void testGetAncestorsWithTypeParameters() {
+    void testGetAncestorsWithTypeParameters() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(8, constructorDeclaration.getAncestors().size());
 
-        ResolvedReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -333,17 +340,17 @@
     }
 
     @Test
-    public void testGetAllAncestorsWithoutTypeParameters() {
+    void testGetAllAncestorsWithoutTypeParameters() {
         JavaParserClassDeclaration cu = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllAncestors().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllAncestorsWithTypeParameters() {
+    void testGetAllAncestorsWithTypeParameters() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(12, constructorDeclaration.getAllAncestors().size());
 
-        ResolvedReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAllAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -395,17 +402,17 @@
     ///
 
     @Test
-    public void testGetFieldForExistingField() {
+    void testGetFieldForExistingField() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        ResolvedFieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         // declared field
         fieldDeclaration = constructorDeclaration.getField("modifiers");
         assertEquals("modifiers", fieldDeclaration.getName());
         assertEquals("java.util.EnumSet", fieldDeclaration.getType().asReferenceType().getQualifiedName());
         assertEquals(AccessSpecifier.PRIVATE, fieldDeclaration.accessSpecifier());
-        assertEquals(false, fieldDeclaration.isStatic());
+        assertFalse(fieldDeclaration.isStatic());
 
         // inherited field
         fieldDeclaration = constructorDeclaration.getField("annotations");
@@ -414,21 +421,23 @@
         assertEquals(AccessSpecifier.PRIVATE, fieldDeclaration.accessSpecifier());
     }
 
-    @Test(expected = UnsolvedSymbolException.class)
-    public void testGetFieldForUnexistingField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
+    @Test
+    void testGetFieldForUnexistingField() {
+        assertThrows(UnsolvedSymbolException.class, () -> {
+            JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         constructorDeclaration.getField("unexisting");
-    }
+    });
+
+}
 
     @Test
-    public void testGetAllFields() {
+    void testGetAllFields() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllFields();
         assertEquals(16, allFields.size());
 
-        ResolvedFieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("modifiers", fieldDeclaration.getName());
@@ -480,10 +489,10 @@
     }
 
     @Test
-    public void testGetAllGenericFields() throws IOException, ParseException {
+    void testGetAllGenericFields() throws IOException {
         TypeSolver typeSolver = new ReflectionTypeSolver();
 
-        CompilationUnit cu = JavaParser.parse(adaptPath(new File("src/test/resources/GenericFields.java.txt")));
+        CompilationUnit cu = parse(adaptPath("src/test/resources/GenericFields.java.txt"));
         JavaParserClassDeclaration classDeclaration = new JavaParserClassDeclaration(Navigator.demandClass(cu, "CB"), typeSolver);
 
         assertEquals(3, classDeclaration.getAllFields().size());
@@ -504,13 +513,13 @@
     }
 
     @Test
-    public void testGetAllStaticFields() {
+    void testGetAllStaticFields() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllStaticFields();
         assertEquals(3, allFields.size());
 
-        ResolvedFieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("NODE_BY_BEGIN_POSITION", fieldDeclaration.getName());
@@ -523,13 +532,13 @@
     }
 
     @Test
-    public void testGetAllNonStaticFields() {
+    void testGetAllNonStaticFields() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllNonStaticFields();
         assertEquals(13, allFields.size());
 
-        ResolvedFieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("modifiers", fieldDeclaration.getName());
@@ -572,13 +581,13 @@
     }
 
     @Test
-    public void testGetDeclaredFields() {
+    void testGetDeclaredFields() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getDeclaredFields();
         assertEquals(6, allFields.size());
 
-        ResolvedFieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("modifiers", fieldDeclaration.getName());
@@ -604,14 +613,14 @@
     ///
 
     @Test
-    public void testGetDeclaredMethods() {
+    void testGetDeclaredMethods() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         Set<ResolvedMethodDeclaration> allMethods = constructorDeclaration.getDeclaredMethods();
         assertEquals(20, allMethods.size());
 
         List<ResolvedMethodDeclaration> sortedMethods = allMethods.stream()
-                .sorted((o1, o2) -> o1.getQualifiedSignature().compareTo(o2.getQualifiedSignature()))
+                .sorted(Comparator.comparing(ResolvedMethodLikeDeclaration::getQualifiedSignature))
                 .collect(Collectors.toList());
 
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)", sortedMethods.get(0).getQualifiedSignature());
@@ -637,13 +646,13 @@
     }
 
     @Test
-    public void testGetAllMethods() {
+    void testGetAllMethods() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         Set<MethodUsage> allMethods = constructorDeclaration.getAllMethods();
 
         List<MethodUsage> sortedMethods = allMethods.stream()
-                .sorted((o1, o2) -> o1.getQualifiedSignature().compareTo(o2.getQualifiedSignature()))
+                .sorted(Comparator.comparing(MethodUsage::getQualifiedSignature))
                 .collect(Collectors.toList());
 
         List<String> signatures = sortedMethods.stream().map(m -> m.getQualifiedSignature()).collect(Collectors.toList());
@@ -756,7 +765,7 @@
     ///
 
     @Test
-    public void testGetConstructors() {
+    void testGetConstructors() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         List<ResolvedConstructorDeclaration> constructors = constructorDeclaration.getConstructors();
@@ -774,10 +783,10 @@
 
     //SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes);
     @Test
-    public void testSolveMethodExisting() {
+    void testSolveMethodExisting() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        SymbolReference<ResolvedMethodDeclaration> res = null;
+        SymbolReference<ResolvedMethodDeclaration> res;
 
         res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of());
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithModifiers.isStatic()", res.getCorrespondingDeclaration().getQualifiedSignature());
@@ -794,29 +803,29 @@
     }
 
     @Test
-    public void testSolveMethodNotExisting() {
+    void testSolveMethodNotExisting() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        SymbolReference<ResolvedMethodDeclaration> res = null;
+        SymbolReference<ResolvedMethodDeclaration> res;
 
         res = constructorDeclaration.solveMethod("unexistingMethod", ImmutableList.of());
-        assertEquals(false, res.isSolved());
+        assertFalse(res.isSolved());
 
         res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of(ResolvedPrimitiveType.BOOLEAN));
-        assertEquals(false, res.isSolved());
+        assertFalse(res.isSolved());
     }
 
     @Test
-    public void testSolveMethodNotExistingBecauseOfTypeParameters() {
+    void testSolveMethodNotExistingBecauseOfTypeParameters() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        SymbolReference<ResolvedMethodDeclaration> res = null;
+        SymbolReference<ResolvedMethodDeclaration> res;
 
         ResolvedReferenceType stringType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(String.class, typeSolverNewCode);
         ResolvedReferenceType rawClassType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(Class.class, typeSolverNewCode);
         ResolvedReferenceType classOfStringType = (ResolvedReferenceType) rawClassType.replaceTypeVariables(rawClassType.getTypeDeclaration().getTypeParameters().get(0), stringType);
         res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(classOfStringType));
-        assertEquals(false, res.isSolved());
+        assertFalse(res.isSolved());
     }
 
 
@@ -837,43 +846,43 @@
     // hasDirectlyAnnotation
 
     @Test
-    public void testHasDirectlyAnnotation() throws IOException, ParseException {
+    void testHasDirectlyAnnotation() throws IOException {
         TypeSolver typeSolver = new ReflectionTypeSolver();
 
-        CompilationUnit cu = JavaParser.parse(adaptPath(new File("src/test/resources/Annotations.java.txt")));
+        CompilationUnit cu = parse(adaptPath("src/test/resources/Annotations.java.txt"));
 
         JavaParserClassDeclaration ca = new JavaParserClassDeclaration(Navigator.demandClass(cu, "CA"), typeSolver);
-        assertEquals(true, ca.hasDirectlyAnnotation("foo.bar.MyAnnotation"));
-        assertEquals(false, ca.hasDirectlyAnnotation("foo.bar.MyAnnotation2"));
-        assertEquals(false, ca.hasDirectlyAnnotation("MyAnnotation"));
-        assertEquals(false, ca.hasDirectlyAnnotation("foo.bar.MyUnexistingAnnotation"));
+        assertTrue(ca.hasDirectlyAnnotation("foo.bar.MyAnnotation"));
+        assertFalse(ca.hasDirectlyAnnotation("foo.bar.MyAnnotation2"));
+        assertFalse(ca.hasDirectlyAnnotation("MyAnnotation"));
+        assertFalse(ca.hasDirectlyAnnotation("foo.bar.MyUnexistingAnnotation"));
 
         JavaParserClassDeclaration cb = new JavaParserClassDeclaration(Navigator.demandClass(cu, "CB"), typeSolver);
-        assertEquals(false, cb.hasDirectlyAnnotation("foo.bar.MyAnnotation"));
-        assertEquals(true, cb.hasDirectlyAnnotation("foo.bar.MyAnnotation2"));
-        assertEquals(false, cb.hasDirectlyAnnotation("MyAnnotation"));
-        assertEquals(false, cb.hasDirectlyAnnotation("foo.bar.MyUnexistingAnnotation"));
+        assertFalse(cb.hasDirectlyAnnotation("foo.bar.MyAnnotation"));
+        assertTrue(cb.hasDirectlyAnnotation("foo.bar.MyAnnotation2"));
+        assertFalse(cb.hasDirectlyAnnotation("MyAnnotation"));
+        assertFalse(cb.hasDirectlyAnnotation("foo.bar.MyUnexistingAnnotation"));
     }
 
     // hasAnnotation
 
     @Test
-    public void testHasAnnotation() throws IOException, ParseException {
+    void testHasAnnotation() throws IOException {
         TypeSolver typeSolver = new ReflectionTypeSolver();
 
-        CompilationUnit cu = JavaParser.parse(adaptPath(new File("src/test/resources/Annotations.java.txt")));
+        CompilationUnit cu = parse(adaptPath("src/test/resources/Annotations.java.txt"));
 
         JavaParserClassDeclaration ca = new JavaParserClassDeclaration(Navigator.demandClass(cu, "CA"), typeSolver);
-        assertEquals(true, ca.hasAnnotation("foo.bar.MyAnnotation"));
-        assertEquals(false, ca.hasAnnotation("foo.bar.MyAnnotation2"));
-        assertEquals(false, ca.hasAnnotation("MyAnnotation"));
-        assertEquals(false, ca.hasAnnotation("foo.bar.MyUnexistingAnnotation"));
+        assertTrue(ca.hasAnnotation("foo.bar.MyAnnotation"));
+        assertFalse(ca.hasAnnotation("foo.bar.MyAnnotation2"));
+        assertFalse(ca.hasAnnotation("MyAnnotation"));
+        assertFalse(ca.hasAnnotation("foo.bar.MyUnexistingAnnotation"));
 
         JavaParserClassDeclaration cb = new JavaParserClassDeclaration(Navigator.demandClass(cu, "CB"), typeSolver);
-        assertEquals(true, cb.hasAnnotation("foo.bar.MyAnnotation"));
-        assertEquals(true, cb.hasAnnotation("foo.bar.MyAnnotation2"));
-        assertEquals(false, cb.hasAnnotation("MyAnnotation"));
-        assertEquals(false, cb.hasAnnotation("foo.bar.MyUnexistingAnnotation"));
+        assertTrue(cb.hasAnnotation("foo.bar.MyAnnotation"));
+        assertTrue(cb.hasAnnotation("foo.bar.MyAnnotation2"));
+        assertFalse(cb.hasAnnotation("MyAnnotation"));
+        assertFalse(cb.hasAnnotation("foo.bar.MyUnexistingAnnotation"));
     }
 
     ///
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclarationTest.java
index c171f4b..77182ff 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclarationTest.java
@@ -16,30 +16,55 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StringProvider;
+import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.*;
+import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
-import static org.junit.Assert.assertEquals;
+import static com.github.javaparser.ast.Modifier.Keyword.PRIVATE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class JavaParserEnumDeclarationTest extends AbstractTest {
+class JavaParserEnumDeclarationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
-        File srcNewCode = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
-        CombinedTypeSolver combinedTypeSolverNewCode = new CombinedTypeSolver();
-        combinedTypeSolverNewCode.add(new ReflectionTypeSolver());
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(srcNewCode));
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
-        typeSolver = combinedTypeSolverNewCode;
+    @BeforeEach
+    void setup() {
+        Path srcNewCode = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
+        CombinedTypeSolver combinedtypeSolver = new CombinedTypeSolver();
+        combinedtypeSolver.add(new ReflectionTypeSolver());
+        combinedtypeSolver.add(new JavaParserTypeSolver(srcNewCode, new LeanParserConfiguration()));
+        combinedtypeSolver.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"), new LeanParserConfiguration()));
+        typeSolver = combinedtypeSolver;
     }
 
     ///
@@ -47,73 +72,77 @@
     ///
 
     @Test
-    public void testIsClass() {
+    void testIsClass() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(false, modifier.isClass());
     }
 
     @Test
-    public void testIsInterface() {
+    void testIsInterface() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(false, modifier.isInterface());
     }
 
     @Test
-    public void testIsEnum() {
+    void testIsEnum() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(true, modifier.isEnum());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(false, modifier.isTypeParameter());
     }
 
     @Test
-    public void testIsType() {
+    void testIsType() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(true, modifier.isType());
     }
 
     @Test
-    public void testAsType() {
+    void testAsType() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(modifier, modifier.asType());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsClass() {
-        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    @Test
+    void testAsClass() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         modifier.asClass();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsInterface() {
-        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        modifier.asInterface();
-    }
+    });
+}
 
     @Test
-    public void testAsEnum() {
+    void testAsInterface() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+        modifier.asInterface();
+    });
+}
+
+    @Test
+    void testAsEnum() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(modifier, modifier.asEnum());
     }
 
     @Test
-    public void testGetPackageName() {
+    void testGetPackageName() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals("com.github.javaparser.ast", modifier.getPackageName());
     }
 
     @Test
-    public void testGetClassName() {
+    void testGetClassName() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals("Modifier", modifier.getClassName());
     }
 
     @Test
-    public void testGetQualifiedName() {
+    void testGetQualifiedName() {
         JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals("com.github.javaparser.ast.Modifier", modifier.getQualifiedName());
     }
@@ -122,31 +151,45 @@
     /// Test ancestors
     ///
 
-    /*@Test
-    public void testGetSuperclassWithoutTypeParameters() {
-        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
+    @Test
+    void getGetAncestors() {
+        Path src = adaptPath("src/test/resources/enums");
+        CombinedTypeSolver combinedtypeSolver = new CombinedTypeSolver();
+        combinedtypeSolver.add(new ReflectionTypeSolver());
+        combinedtypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+
+        JavaParserEnumDeclaration enum1 = (JavaParserEnumDeclaration) combinedtypeSolver.solveType("EnumWithAncestor");
+        List<ResolvedReferenceType> ancestors = enum1.getAncestors();
+        assertEquals(2, ancestors.size());
+        assertEquals("java.lang.Enum", ancestors.get(0).getQualifiedName());
+        assertEquals("java.lang.Cloneable", ancestors.get(1).getQualifiedName());
     }
 
+//    @Test
+//    public void testGetSuperclassWithoutTypeParameters() {
+//        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+//        assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
+//    }
+
     @Test
-    public void testGetSuperclassWithTypeParameters() {
-        JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetSuperclassWithTypeParameters() {
+        JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", compilationUnit.getSuperClass().getQualifiedName());
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", compilationUnit.getSuperClass().typeParametersMap().getValueBySignature("com.github.javaparser.ast.body.BodyDeclaration.T").get().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void testGetAllSuperclassesWithoutTypeParameters() {
+    void testGetAllSuperclassesWithoutTypeParameters() {
         JavaParserClassDeclaration cu = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllSuperclassesWithTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllSuperclassesWithTypeParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(3, constructorDeclaration.getAllSuperClasses().size());
 
-        ReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAllSuperClasses().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -159,21 +202,21 @@
         assertEquals("java.lang.Object", ancestor.getQualifiedName());
     }
 
-    @Test
-    public void testGetInterfacesWithoutParameters() {
-        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-
-        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.DocumentableNode"), coid.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-    }
+//    @Test
+//    public void testGetInterfacesWithoutParameters() {
+//        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+//        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//
+//        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
+//        assertEquals(ImmutableSet.of("com.github.javaparser.ast.DocumentableNode"), coid.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//    }
 
     @Test
-    public void testGetInterfacesWithParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetInterfacesWithParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(7, constructorDeclaration.getInterfaces().size());
 
-        ReferenceType interfaze = null;
+        ResolvedReferenceType interfaze;
 
         interfaze = constructorDeclaration.getInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -203,21 +246,21 @@
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", interfaze.typeParametersMap().getValueBySignature("com.github.javaparser.ast.nodeTypes.NodeWithBlockStmt.T").get().asReferenceType().getQualifiedName());
     }
 
-    @Test
-    public void testGetAllInterfacesWithoutParameters() {
-        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        assertEquals(ImmutableSet.of("java.lang.Cloneable"), compilationUnit.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-
-        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
-        assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.NamedNode", "com.github.javaparser.ast.body.AnnotableNode", "com.github.javaparser.ast.DocumentableNode"), coid.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-    }
+//    @Test
+//    public void testGetAllInterfacesWithoutParameters() {
+//        JavaParserEnumDeclaration modifier = (JavaParserEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+//        assertEquals(ImmutableSet.of("java.lang.Cloneable"), compilationUnit.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//
+//        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
+//        assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.NamedNode", "com.github.javaparser.ast.body.AnnotableNode", "com.github.javaparser.ast.DocumentableNode"), coid.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//    }
 
     @Test
-    public void testGetAllInterfacesWithParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllInterfacesWithParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(9, constructorDeclaration.getAllInterfaces().size());
 
-        ReferenceType interfaze = null;
+        ResolvedReferenceType interfaze;
 
         interfaze = constructorDeclaration.getAllInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -255,11 +298,11 @@
     }
 
     @Test
-    public void testGetAncestorsWithTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAncestorsWithTypeParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(8, constructorDeclaration.getAncestors().size());
 
-        ReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -294,17 +337,17 @@
     }
 
     @Test
-    public void testGetAllAncestorsWithoutTypeParameters() {
+    void testGetAllAncestorsWithoutTypeParameters() {
         JavaParserClassDeclaration cu = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllAncestors().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllAncestorsWithTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllAncestorsWithTypeParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(12, constructorDeclaration.getAllAncestors().size());
 
-        ReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAllAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -356,40 +399,42 @@
     ///
 
     @Test
-    public void testGetFieldForExistingField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetFieldForExistingField() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         // declared field
         fieldDeclaration = constructorDeclaration.getField("modifiers");
         assertEquals("modifiers", fieldDeclaration.getName());
         assertEquals("java.util.EnumSet", fieldDeclaration.getType().asReferenceType().getQualifiedName());
-        assertEquals(AccessLevel.PRIVATE, fieldDeclaration.accessLevel());
-        assertEquals(false, fieldDeclaration.isStatic());
+        assertEquals(AccessSpecifier.PRIVATE, fieldDeclaration.accessSpecifier());
+        assertFalse(fieldDeclaration.isStatic());
 
         // inherited field
         fieldDeclaration = constructorDeclaration.getField("annotations");
         assertEquals("annotations", fieldDeclaration.getName());
         assertEquals("java.util.List", fieldDeclaration.getType().asReferenceType().getQualifiedName());
-        assertEquals(AccessLevel.PRIVATE, fieldDeclaration.accessLevel());
-    }
-
-    @Test(expected = UnsolvedSymbolException.class)
-    public void testGetFieldForUnexistingField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        constructorDeclaration.getField("unexisting");
+        assertEquals(AccessSpecifier.PRIVATE, fieldDeclaration.accessSpecifier());
     }
 
     @Test
-    public void testGetAllFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetFieldForUnexistingField() {
+        assertThrows(UnsolvedSymbolException.class, () -> {
+            JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+        constructorDeclaration.getField("unexisting");
+    });
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getAllFields();
+}
+
+    @Test
+    void testGetAllFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllFields();
         assertEquals(16, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("modifiers", fieldDeclaration.getName());
@@ -441,13 +486,13 @@
     }
 
     @Test
-    public void testGetAllStaticFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllStaticFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getAllStaticFields();
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllStaticFields();
         assertEquals(3, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("NODE_BY_BEGIN_POSITION", fieldDeclaration.getName());
@@ -460,13 +505,13 @@
     }
 
     @Test
-    public void testGetAllNonStaticFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllNonStaticFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getAllNonStaticFields();
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllNonStaticFields();
         assertEquals(13, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("modifiers", fieldDeclaration.getName());
@@ -509,13 +554,13 @@
     }
 
     @Test
-    public void testGetDeclaredFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetDeclaredFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getDeclaredFields();
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getDeclaredFields();
         assertEquals(6, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration fieldDeclaration;
 
         fieldDeclaration = allFields.get(0);
         assertEquals("modifiers", fieldDeclaration.getName());
@@ -541,14 +586,14 @@
     ///
 
     @Test
-    public void testGetDeclaredMethods() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetDeclaredMethods() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        Set<MethodDeclaration> allMethods = constructorDeclaration.getDeclaredMethods();
+        Set<ResolvedMethodDeclaration> allMethods = constructorDeclaration.getDeclaredMethods();
         assertEquals(20, allMethods.size());
 
-        List<MethodDeclaration> sortedMethods = allMethods.stream()
-                .sorted((o1, o2) -> o1.getQualifiedSignature().compareTo(o2.getQualifiedSignature()))
+        List<ResolvedMethodDeclaration> sortedMethods = allMethods.stream()
+                .sorted(Comparator.comparing(ResolvedMethodLikeDeclaration::getQualifiedSignature))
                 .collect(Collectors.toList());
 
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)", sortedMethods.get(0).getQualifiedSignature());
@@ -574,13 +619,13 @@
     }
 
     @Test
-    public void testGetAllMethods() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllMethods() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         Set<MethodUsage> allMethods = constructorDeclaration.getAllMethods();
 
         List<MethodUsage> sortedMethods = allMethods.stream()
-                .sorted((o1, o2) -> o1.getQualifiedSignature().compareTo(o2.getQualifiedSignature()))
+                .sorted(Comparator.comparing(MethodUsage::getQualifiedSignature))
                 .collect(Collectors.toList());
 
         List<String> signatures = sortedMethods.stream().map(m -> m.getQualifiedSignature()).collect(Collectors.toList());
@@ -693,10 +738,10 @@
     ///
 
     @Test
-    public void testGetConstructors() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetConstructors() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<ConstructorDeclaration> constructors = constructorDeclaration.getConstructors();
+        List<ResolvedConstructorDeclaration> constructors = constructorDeclaration.getConstructors();
         assertEquals(4, constructors.size());
 
         assertEquals("ConstructorDeclaration()", constructors.get(0).getSignature());
@@ -711,84 +756,84 @@
 
     //SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes);
     @Test
-    public void testSolveMethodExisting() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testSolveMethodExisting() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        SymbolReference<MethodDeclaration> res = null;
+        SymbolReference<ResolvedMethodDeclaration> res;
 
         res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of());
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithModifiers.isStatic()", res.getCorrespondingDeclaration().getQualifiedSignature());
 
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(RuntimeException.class.getClass(), typeSolverNewCode)));
+        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(RuntimeException.class.getClass(), typeSolver)));
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithThrowable.isThrows(java.lang.Class<? extends java.lang.Throwable>)", res.getCorrespondingDeclaration().getQualifiedSignature());
 
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(String.class, typeSolverNewCode)));
+        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(String.class, typeSolver)));
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithThrowable.isThrows(java.lang.String)", res.getCorrespondingDeclaration().getQualifiedSignature());
 
         // This is solved because it is raw
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(Class.class, typeSolverNewCode)));
+        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(Class.class, typeSolver)));
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithThrowable.isThrows(java.lang.Class<? extends java.lang.Throwable>)", res.getCorrespondingDeclaration().getQualifiedSignature());
     }
 
     @Test
-    public void testSolveMethodNotExisting() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testSolveMethodNotExisting() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        SymbolReference<MethodDeclaration> res = null;
+        SymbolReference<ResolvedMethodDeclaration> res;
 
         res = constructorDeclaration.solveMethod("unexistingMethod", ImmutableList.of());
         assertEquals(false, res.isSolved());
 
-        res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of(PrimitiveType.BOOLEAN));
+        res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of(ResolvedPrimitiveType.BOOLEAN));
         assertEquals(false, res.isSolved());
     }
 
-    @Test
-    public void testSolveMethodNotExistingBecauseOfTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//    @Test
+//    public void testSolveMethodNotExistingBecauseOfTypeParameters() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<ResolvedMethodDeclaration> res = null;
+//
+//        ResolvedReferenceType stringType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(String.class, typeSolver);
+//        ResolvedReferenceType rawClassType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(Class.class, typeSolver);
+//        ResolvedReferenceType classOfStringType = (ResolvedReferenceType) rawClassType.replaceTypeVariables("T", stringType);
+//        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(classOfStringType));
+//        assertEquals(false, res.isSolved());
+//    }
 
-        SymbolReference<MethodDeclaration> res = null;
-
-        ReferenceType stringType = (ReferenceType) ReflectionFactory.typeUsageFor(String.class, typeSolverNewCode);
-        ReferenceType rawClassType = (ReferenceType) ReflectionFactory.typeUsageFor(Class.class, typeSolverNewCode);
-        ReferenceType classOfStringType = (ReferenceType) rawClassType.replaceTypeVariables("T", stringType);
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(classOfStringType));
-        assertEquals(false, res.isSolved());
-    }
-
-    @Test
-    public void testSolveSymbolUnexisting() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("unexisting", typeSolver);
-        assertEquals(false, res.isSolved());
-    }
-
-    @Test
-    public void testSolveSymbolToDeclaredField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("name", typeSolver);
-        assertEquals(true, res.isSolved());
-        assertEquals(true, res.getCorrespondingDeclaration().isField());
-    }
-
-    @Test
-    public void testSolveSymbolToInheritedPublicField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("NODE_BY_BEGIN_POSITION", typeSolver);
-        assertEquals(true, res.isSolved());
-        assertEquals(true, res.getCorrespondingDeclaration().isField());
-    }
-
-    @Test
-    public void testSolveSymbolToInheritedPrivateField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("parentNode", typeSolver);
-        assertEquals(false, res.isSolved());
-    }
+//    @Test
+//    public void testSolveSymbolUnexisting() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ResolvedValueDeclaration> res = constructorDeclaration.solveSymbol("unexisting", typeSolver);
+//        assertEquals(false, res.isSolved());
+//    }
+//
+//    @Test
+//    public void testSolveSymbolToDeclaredField() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ResolvedValueDeclaration> res = constructorDeclaration.solveSymbol("name", typeSolver);
+//        assertEquals(true, res.isSolved());
+//        assertEquals(true, res.getCorrespondingDeclaration().isField());
+//    }
+//
+//    @Test
+//    public void testSolveSymbolToInheritedPublicField() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ResolvedValueDeclaration> res = constructorDeclaration.solveSymbol("NODE_BY_BEGIN_POSITION", typeSolver);
+//        assertEquals(true, res.isSolved());
+//        assertEquals(true, res.getCorrespondingDeclaration().isField());
+//    }
+//
+//    @Test
+//    public void testSolveSymbolToInheritedPrivateField() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ResolvedValueDeclaration> res = constructorDeclaration.solveSymbol("parentNode", typeSolver);
+//        assertEquals(false, res.isSolved());
+//    }
 
     ///
     /// Assignability
@@ -822,5 +867,42 @@
 
     // Set<TypeDeclaration> internalTypes()
 
-    // Optional<TypeDeclaration> containerType()*/
+    // Optional<TypeDeclaration> containerType()
+
+    ///
+    /// Annotations
+    ///
+
+    // Issue 1749
+    @Test
+    void testHasDirectlyAnnotationNegative() {
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(
+                new JavaSymbolSolver(new ReflectionTypeSolver()));
+        CompilationUnit cu = new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT,
+                new StringProvider("public class Employee {"
+                        + "    public enum Weekend { SUNDAY, SATURDAY }"
+                        + "    private Weekend weekend;"
+                        + "}"
+        )).getResult().get();
+        FieldDeclaration field = cu.getClassByName("Employee").get().getMembers().get(1).asFieldDeclaration();
+        ResolvedReferenceTypeDeclaration dec = field.getElementType().resolve().asReferenceType().getTypeDeclaration();
+        assertEquals(false, dec.hasDirectlyAnnotation("javax.persistence.Embeddable"));
+    }
+
+    // Issue 1749
+    @Test
+    void testHasDirectlyAnnotationPositive() {
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(
+                new JavaSymbolSolver(new ReflectionTypeSolver()));
+        CompilationUnit cu = new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT,
+                new StringProvider("@interface MyAnno {} public class Employee {"
+                        + "    public @MyAnno enum Weekend { SUNDAY, SATURDAY }"
+                        + "    private Weekend weekend;"
+                        + "}"
+                )).getResult().get();
+        FieldDeclaration field = cu.getClassByName("Employee").get().getMembers().get(1).asFieldDeclaration();
+        ResolvedReferenceTypeDeclaration dec = field.getElementType().resolve().asReferenceType().getTypeDeclaration();
+        assertEquals(false, dec.hasDirectlyAnnotation("javax.persistence.Embeddable"));
+        assertEquals(true, dec.hasDirectlyAnnotation("MyAnno"));
+    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclarationTest.java
index cf5e580..664aaa7 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclarationTest.java
@@ -16,30 +16,54 @@
 
 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
 
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.*;
+import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
-import static org.junit.Assert.assertEquals;
+import static com.github.javaparser.ast.Modifier.Keyword.PRIVATE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class JavaParserInterfaceDeclarationTest extends AbstractTest {
+class JavaParserInterfaceDeclarationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
-        File srcNewCode = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
-        CombinedTypeSolver combinedTypeSolverNewCode = new CombinedTypeSolver();
-        combinedTypeSolverNewCode.add(new ReflectionTypeSolver());
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(srcNewCode));
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
-        typeSolver = combinedTypeSolverNewCode;
+    @BeforeEach
+    void setup() {
+        Path srcNewCode = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
+        CombinedTypeSolver combinedtypeSolver = new CombinedTypeSolver();
+        combinedtypeSolver.add(new ReflectionTypeSolver());
+        combinedtypeSolver.add(new JavaParserTypeSolver(srcNewCode, new LeanParserConfiguration()));
+        combinedtypeSolver.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"), new LeanParserConfiguration()));
+        typeSolver = combinedtypeSolver;
     }
 
     ///
@@ -47,73 +71,77 @@
     ///
 
     @Test
-    public void testIsClass() {
+    void testIsClass() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(false, nodeWithAnnotations.isClass());
     }
 
     @Test
-    public void testIsInterface() {
+    void testIsInterface() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(true, nodeWithAnnotations.isInterface());
     }
 
     @Test
-    public void testIsEnum() {
+    void testIsEnum() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(false, nodeWithAnnotations.isEnum());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(false, nodeWithAnnotations.isTypeParameter());
     }
 
     @Test
-    public void testIsType() {
+    void testIsType() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(true, nodeWithAnnotations.isType());
     }
 
     @Test
-    public void testAsType() {
+    void testAsType() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(nodeWithAnnotations, nodeWithAnnotations.asType());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsClass() {
-        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
-        assertEquals(nodeWithAnnotations, nodeWithAnnotations.asClass());
+    @Test
+    void testAsClass() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
+            assertEquals(nodeWithAnnotations, nodeWithAnnotations.asClass());
+        });
     }
 
     @Test
-    public void testAsInterface() {
+    void testAsInterface() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(nodeWithAnnotations, nodeWithAnnotations.asInterface());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsEnum() {
-        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
-        nodeWithAnnotations.asEnum();
+    @Test
+    void testAsEnum() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
+            nodeWithAnnotations.asEnum();
+        });
     }
 
     @Test
-    public void testGetPackageName() {
+    void testGetPackageName() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals("com.github.javaparser.ast.nodeTypes", nodeWithAnnotations.getPackageName());
     }
 
     @Test
-    public void testGetClassName() {
+    void testGetClassName() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals("NodeWithAnnotations", nodeWithAnnotations.getClassName());
     }
 
     @Test
-    public void testGetQualifiedName() {
+    void testGetQualifiedName() {
         JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations", nodeWithAnnotations.getQualifiedName());
     }
@@ -122,31 +150,48 @@
     /// Test ancestors
     ///
 
-    /*@Test
-    public void testGetSuperclassWithoutTypeParameters() {
-        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
-        assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
-    }
+//    @Test
+//    public void testGetSuperclassWithoutTypeParameters() {
+//        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
+//        assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
+//    }
 
     @Test
-    public void testGetSuperclassWithTypeParameters() {
-        JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetSuperclassWithTypeParameters() {
+        JavaParserClassDeclaration compilationUnit = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", compilationUnit.getSuperClass().getQualifiedName());
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", compilationUnit.getSuperClass().typeParametersMap().getValueBySignature("com.github.javaparser.ast.body.BodyDeclaration.T").get().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void testGetAllSuperclassesWithoutTypeParameters() {
+    void testGetAllSuperclassesWithoutTypeParameters() {
         JavaParserClassDeclaration cu = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllSuperclassesWithTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void getGetAncestorsWithTypeParameters() {
+        Path src = adaptPath("src/test/resources/recursion-issue");
+        CombinedTypeSolver combinedtypeSolver = new CombinedTypeSolver();
+        combinedtypeSolver.add(new ReflectionTypeSolver());
+        combinedtypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+
+        JavaParserInterfaceDeclaration validator = (JavaParserInterfaceDeclaration) combinedtypeSolver.solveType("Extends");
+        List<ResolvedReferenceType> ancestors = validator.getAncestors();
+        assertEquals(1, ancestors.size());
+        assertEquals("Base", ancestors.get(0).getQualifiedName());
+        List<ResolvedType> types = ancestors.get(0).typeParametersValues();
+        assertEquals(2, types.size());
+        assertEquals("java.lang.Integer", types.get(0).asReferenceType().getQualifiedName());
+        assertEquals("Extends", types.get(1).asReferenceType().getQualifiedName());
+    }
+
+    @Test
+    void testGetAllSuperclassesWithTypeParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(3, constructorDeclaration.getAllSuperClasses().size());
 
-        ReferenceType ancestor = null;
+        ResolvedReferenceType ancestor = null;
 
         ancestor = constructorDeclaration.getAllSuperClasses().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -159,21 +204,21 @@
         assertEquals("java.lang.Object", ancestor.getQualifiedName());
     }
 
-    @Test
-    public void testGetInterfacesWithoutParameters() {
-        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
-        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-
-        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.DocumentableNode"), coid.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-    }
+//    @Test
+//    public void testGetInterfacesWithoutParameters() {
+//        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
+//        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//
+//        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
+//        assertEquals(ImmutableSet.of("com.github.javaparser.ast.DocumentableNode"), coid.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//    }
 
     @Test
-    public void testGetInterfacesWithParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetInterfacesWithParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(7, constructorDeclaration.getInterfaces().size());
 
-        ReferenceType interfaze = null;
+        ResolvedReferenceType interfaze = null;
 
         interfaze = constructorDeclaration.getInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -203,21 +248,21 @@
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", interfaze.typeParametersMap().getValueBySignature("com.github.javaparser.ast.nodeTypes.NodeWithBlockStmt.T").get().asReferenceType().getQualifiedName());
     }
 
-    @Test
-    public void testGetAllInterfacesWithoutParameters() {
-        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
-        assertEquals(ImmutableSet.of("java.lang.Cloneable"), compilationUnit.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-
-        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
-        assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.NamedNode", "com.github.javaparser.ast.body.AnnotableNode", "com.github.javaparser.ast.DocumentableNode"), coid.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
-    }
+//    @Test
+//    public void testGetAllInterfacesWithoutParameters() {
+//        JavaParserInterfaceDeclaration nodeWithAnnotations = (JavaParserInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
+//        assertEquals(ImmutableSet.of("java.lang.Cloneable"), compilationUnit.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//
+//        JavaParserClassDeclaration coid = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
+//        assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.NamedNode", "com.github.javaparser.ast.body.AnnotableNode", "com.github.javaparser.ast.DocumentableNode"), coid.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+//    }
 
     @Test
-    public void testGetAllInterfacesWithParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllInterfacesWithParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(9, constructorDeclaration.getAllInterfaces().size());
 
-        ReferenceType interfaze = null;
+        ResolvedReferenceType interfaze;
 
         interfaze = constructorDeclaration.getAllInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -255,11 +300,11 @@
     }
 
     @Test
-    public void testGetAncestorsWithTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAncestorsWithTypeParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(8, constructorDeclaration.getAncestors().size());
 
-        ReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -294,17 +339,17 @@
     }
 
     @Test
-    public void testGetAllAncestorsWithoutTypeParameters() {
+    void testGetAllAncestorsWithoutTypeParameters() {
         JavaParserClassDeclaration cu = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllAncestors().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllAncestorsWithTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllAncestorsWithTypeParameters() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(12, constructorDeclaration.getAllAncestors().size());
 
-        ReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAllAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -356,184 +401,186 @@
     ///
 
     @Test
-    public void testGetFieldForExistingField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetFieldForExistingField() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration ResolvedFieldDeclaration;
 
         // declared field
-        fieldDeclaration = constructorDeclaration.getField("modifiers");
-        assertEquals("modifiers", fieldDeclaration.getName());
-        assertEquals("java.util.EnumSet", fieldDeclaration.getType().asReferenceType().getQualifiedName());
-        assertEquals(AccessLevel.PRIVATE, fieldDeclaration.accessLevel());
-        assertEquals(false, fieldDeclaration.isStatic());
+        ResolvedFieldDeclaration = constructorDeclaration.getField("modifiers");
+        assertEquals("modifiers", ResolvedFieldDeclaration.getName());
+        assertEquals("java.util.EnumSet", ResolvedFieldDeclaration.getType().asReferenceType().getQualifiedName());
+        assertEquals(AccessSpecifier.PRIVATE, ResolvedFieldDeclaration.accessSpecifier());
+        assertEquals(false, ResolvedFieldDeclaration.isStatic());
 
         // inherited field
-        fieldDeclaration = constructorDeclaration.getField("annotations");
-        assertEquals("annotations", fieldDeclaration.getName());
-        assertEquals("java.util.List", fieldDeclaration.getType().asReferenceType().getQualifiedName());
-        assertEquals(AccessLevel.PRIVATE, fieldDeclaration.accessLevel());
-    }
-
-    @Test(expected = UnsolvedSymbolException.class)
-    public void testGetFieldForUnexistingField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        constructorDeclaration.getField("unexisting");
+        ResolvedFieldDeclaration = constructorDeclaration.getField("annotations");
+        assertEquals("annotations", ResolvedFieldDeclaration.getName());
+        assertEquals("java.util.List", ResolvedFieldDeclaration.getType().asReferenceType().getQualifiedName());
+        assertEquals(AccessSpecifier.PRIVATE, ResolvedFieldDeclaration.accessSpecifier());
     }
 
     @Test
-    public void testGetAllFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetFieldForUnexistingField() {
+        assertThrows(UnsolvedSymbolException.class, () -> {
+            JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+            constructorDeclaration.getField("unexisting");
+        });
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getAllFields();
+    }
+
+    @Test
+    void testGetAllFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllFields();
         assertEquals(16, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration ResolvedFieldDeclaration;
 
-        fieldDeclaration = allFields.get(0);
-        assertEquals("modifiers", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(0);
+        assertEquals("modifiers", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(1);
-        assertEquals("typeParameters", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(1);
+        assertEquals("typeParameters", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(2);
-        assertEquals("name", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(2);
+        assertEquals("name", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(3);
-        assertEquals("parameters", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(3);
+        assertEquals("parameters", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(4);
-        assertEquals("throws_", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(4);
+        assertEquals("throws_", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(5);
-        assertEquals("body", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(5);
+        assertEquals("body", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(6);
-        assertEquals("annotations", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(6);
+        assertEquals("annotations", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(7);
-        assertEquals("NODE_BY_BEGIN_POSITION", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(7);
+        assertEquals("NODE_BY_BEGIN_POSITION", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(8);
-        assertEquals("range", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(8);
+        assertEquals("range", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(9);
-        assertEquals("parentNode", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(9);
+        assertEquals("parentNode", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(10);
-        assertEquals("childrenNodes", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(10);
+        assertEquals("childrenNodes", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(11);
-        assertEquals("orphanComments", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(11);
+        assertEquals("orphanComments", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(12);
-        assertEquals("userData", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(12);
+        assertEquals("userData", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(13);
-        assertEquals("comment", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(13);
+        assertEquals("comment", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(14);
-        assertEquals("ABSOLUTE_BEGIN_LINE", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(14);
+        assertEquals("ABSOLUTE_BEGIN_LINE", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(15);
-        assertEquals("ABSOLUTE_END_LINE", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(15);
+        assertEquals("ABSOLUTE_END_LINE", ResolvedFieldDeclaration.getName());
     }
 
     @Test
-    public void testGetAllStaticFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllStaticFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getAllStaticFields();
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllStaticFields();
         assertEquals(3, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration ResolvedFieldDeclaration;
 
-        fieldDeclaration = allFields.get(0);
-        assertEquals("NODE_BY_BEGIN_POSITION", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(0);
+        assertEquals("NODE_BY_BEGIN_POSITION", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(1);
-        assertEquals("ABSOLUTE_BEGIN_LINE", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(1);
+        assertEquals("ABSOLUTE_BEGIN_LINE", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(2);
-        assertEquals("ABSOLUTE_END_LINE", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(2);
+        assertEquals("ABSOLUTE_END_LINE", ResolvedFieldDeclaration.getName());
     }
 
     @Test
-    public void testGetAllNonStaticFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllNonStaticFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getAllNonStaticFields();
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getAllNonStaticFields();
         assertEquals(13, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration ResolvedFieldDeclaration;
 
-        fieldDeclaration = allFields.get(0);
-        assertEquals("modifiers", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(0);
+        assertEquals("modifiers", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(1);
-        assertEquals("typeParameters", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(1);
+        assertEquals("typeParameters", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(2);
-        assertEquals("name", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(2);
+        assertEquals("name", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(3);
-        assertEquals("parameters", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(3);
+        assertEquals("parameters", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(4);
-        assertEquals("throws_", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(4);
+        assertEquals("throws_", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(5);
-        assertEquals("body", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(5);
+        assertEquals("body", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(6);
-        assertEquals("annotations", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(6);
+        assertEquals("annotations", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(7);
-        assertEquals("range", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(7);
+        assertEquals("range", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(8);
-        assertEquals("parentNode", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(8);
+        assertEquals("parentNode", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(9);
-        assertEquals("childrenNodes", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(9);
+        assertEquals("childrenNodes", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(10);
-        assertEquals("orphanComments", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(10);
+        assertEquals("orphanComments", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(11);
-        assertEquals("userData", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(11);
+        assertEquals("userData", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(12);
-        assertEquals("comment", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(12);
+        assertEquals("comment", ResolvedFieldDeclaration.getName());
     }
 
     @Test
-    public void testGetDeclaredFields() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetDeclaredFields() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<FieldDeclaration> allFields = constructorDeclaration.getDeclaredFields();
+        List<ResolvedFieldDeclaration> allFields = constructorDeclaration.getDeclaredFields();
         assertEquals(6, allFields.size());
 
-        FieldDeclaration fieldDeclaration = null;
+        ResolvedFieldDeclaration ResolvedFieldDeclaration;
 
-        fieldDeclaration = allFields.get(0);
-        assertEquals("modifiers", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(0);
+        assertEquals("modifiers", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(1);
-        assertEquals("typeParameters", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(1);
+        assertEquals("typeParameters", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(2);
-        assertEquals("name", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(2);
+        assertEquals("name", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(3);
-        assertEquals("parameters", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(3);
+        assertEquals("parameters", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(4);
-        assertEquals("throws_", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(4);
+        assertEquals("throws_", ResolvedFieldDeclaration.getName());
 
-        fieldDeclaration = allFields.get(5);
-        assertEquals("body", fieldDeclaration.getName());
+        ResolvedFieldDeclaration = allFields.get(5);
+        assertEquals("body", ResolvedFieldDeclaration.getName());
     }
 
     ///
@@ -541,14 +588,14 @@
     ///
 
     @Test
-    public void testGetDeclaredMethods() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetDeclaredMethods() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        Set<MethodDeclaration> allMethods = constructorDeclaration.getDeclaredMethods();
+        Set<ResolvedMethodDeclaration> allMethods = constructorDeclaration.getDeclaredMethods();
         assertEquals(20, allMethods.size());
 
-        List<MethodDeclaration> sortedMethods = allMethods.stream()
-                .sorted((o1, o2) -> o1.getQualifiedSignature().compareTo(o2.getQualifiedSignature()))
+        List<ResolvedMethodDeclaration> sortedMethods = allMethods.stream()
+                .sorted(Comparator.comparing(ResolvedMethodLikeDeclaration::getQualifiedSignature))
                 .collect(Collectors.toList());
 
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)", sortedMethods.get(0).getQualifiedSignature());
@@ -574,13 +621,13 @@
     }
 
     @Test
-    public void testGetAllMethods() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetAllMethods() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         Set<MethodUsage> allMethods = constructorDeclaration.getAllMethods();
 
         List<MethodUsage> sortedMethods = allMethods.stream()
-                .sorted((o1, o2) -> o1.getQualifiedSignature().compareTo(o2.getQualifiedSignature()))
+                .sorted(Comparator.comparing(MethodUsage::getQualifiedSignature))
                 .collect(Collectors.toList());
 
         List<String> signatures = sortedMethods.stream().map(m -> m.getQualifiedSignature()).collect(Collectors.toList());
@@ -693,10 +740,10 @@
     ///
 
     @Test
-    public void testGetConstructors() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testGetConstructors() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        List<ConstructorDeclaration> constructors = constructorDeclaration.getConstructors();
+        List<ResolvedConstructorDeclaration> constructors = constructorDeclaration.getConstructors();
         assertEquals(4, constructors.size());
 
         assertEquals("ConstructorDeclaration()", constructors.get(0).getSignature());
@@ -711,84 +758,84 @@
 
     //SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes);
     @Test
-    public void testSolveMethodExisting() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testSolveMethodExisting() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        SymbolReference<MethodDeclaration> res = null;
+        SymbolReference<ResolvedMethodDeclaration> res;
 
         res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of());
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithModifiers.isStatic()", res.getCorrespondingDeclaration().getQualifiedSignature());
 
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(RuntimeException.class.getClass(), typeSolverNewCode)));
+        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(RuntimeException.class.getClass(), typeSolver)));
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithThrowable.isThrows(java.lang.Class<? extends java.lang.Throwable>)", res.getCorrespondingDeclaration().getQualifiedSignature());
 
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(String.class, typeSolverNewCode)));
+        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(String.class, typeSolver)));
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithThrowable.isThrows(java.lang.String)", res.getCorrespondingDeclaration().getQualifiedSignature());
 
         // This is solved because it is raw
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(Class.class, typeSolverNewCode)));
+        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(ReflectionFactory.typeUsageFor(Class.class, typeSolver)));
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithThrowable.isThrows(java.lang.Class<? extends java.lang.Throwable>)", res.getCorrespondingDeclaration().getQualifiedSignature());
     }
 
     @Test
-    public void testSolveMethodNotExisting() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+    void testSolveMethodNotExisting() {
+        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
-        SymbolReference<MethodDeclaration> res = null;
+        SymbolReference<ResolvedMethodDeclaration> res;
 
         res = constructorDeclaration.solveMethod("unexistingMethod", ImmutableList.of());
         assertEquals(false, res.isSolved());
 
-        res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of(PrimitiveType.BOOLEAN));
+        res = constructorDeclaration.solveMethod("isStatic", ImmutableList.of(ResolvedPrimitiveType.BOOLEAN));
         assertEquals(false, res.isSolved());
     }
 
-    @Test
-    public void testSolveMethodNotExistingBecauseOfTypeParameters() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<MethodDeclaration> res = null;
-
-        ReferenceType stringType = (ReferenceType) ReflectionFactory.typeUsageFor(String.class, typeSolverNewCode);
-        ReferenceType rawClassType = (ReferenceType) ReflectionFactory.typeUsageFor(Class.class, typeSolverNewCode);
-        ReferenceType classOfStringType = (ReferenceType) rawClassType.replaceTypeVariables("T", stringType);
-        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(classOfStringType));
-        assertEquals(false, res.isSolved());
-    }
-
-    @Test
-    public void testSolveSymbolUnexisting() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("unexisting", typeSolver);
-        assertEquals(false, res.isSolved());
-    }
-
-    @Test
-    public void testSolveSymbolToDeclaredField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("name", typeSolver);
-        assertEquals(true, res.isSolved());
-        assertEquals(true, res.getCorrespondingDeclaration().isField());
-    }
-
-    @Test
-    public void testSolveSymbolToInheritedPublicField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("NODE_BY_BEGIN_POSITION", typeSolver);
-        assertEquals(true, res.isSolved());
-        assertEquals(true, res.getCorrespondingDeclaration().isField());
-    }
-
-    @Test
-    public void testSolveSymbolToInheritedPrivateField() {
-        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
-
-        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("parentNode", typeSolver);
-        assertEquals(false, res.isSolved());
-    }
+//    @Test
+//    public void testSolveMethodNotExistingBecauseOfTypeParameters() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<ResolvedMethodDeclaration> res = null;
+//
+//        ResolvedReferenceType stringType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(String.class, typeSolver);
+//        ResolvedReferenceType rawClassType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(Class.class, typeSolver);
+//        ResolvedReferenceType classOfStringType = (ResolvedReferenceType) rawClassType.replaceTypeVariables("T", stringType);
+//        res = constructorDeclaration.solveMethod("isThrows", ImmutableList.of(classOfStringType));
+//        assertEquals(false, res.isSolved());
+//    }
+//
+//    @Test
+//    public void testSolveSymbolUnexisting() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("unexisting", typeSolver);
+//        assertEquals(false, res.isSolved());
+//    }
+//
+//    @Test
+//    public void testSolveSymbolToDeclaredField() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("name", typeSolver);
+//        assertEquals(true, res.isSolved());
+//        assertEquals(true, res.getCorrespondingDeclaration().isField());
+//    }
+//
+//    @Test
+//    public void testSolveSymbolToInheritedPublicField() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("NODE_BY_BEGIN_POSITION", typeSolver);
+//        assertEquals(true, res.isSolved());
+//        assertEquals(true, res.getCorrespondingDeclaration().isField());
+//    }
+//
+//    @Test
+//    public void testSolveSymbolToInheritedPrivateField() {
+//        JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
+//
+//        SymbolReference<? extends ValueDeclaration> res = constructorDeclaration.solveSymbol("parentNode", typeSolver);
+//        assertEquals(false, res.isSolved());
+//    }
 
     ///
     /// Assignability
@@ -814,7 +861,7 @@
 
     // List<TypeParameterDeclaration> getTypeParameters();
 
-    // AccessLevel accessLevel();
+    // AccessSpecifier accessLevel();
 
     ///
     /// Containment
@@ -822,5 +869,23 @@
 
     // Set<TypeDeclaration> internalTypes()
 
-    // Optional<TypeDeclaration> containerType()*/
+    // Optional<TypeDeclaration> containerType()
+
+    @Test
+    void issue1528() {
+        try {
+            TypeSolver typeSolver = new ReflectionTypeSolver();
+            StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
+            JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
+            CompilationUnit compilationUnit = StaticJavaParser.parse("public interface Foo extends Comparable { }");
+            ClassOrInterfaceDeclaration foo = (ClassOrInterfaceDeclaration) compilationUnit.getType(0);
+            ResolvedInterfaceDeclaration interfaceDeclaration = javaParserFacade.getTypeDeclaration(foo).asInterface();
+
+            ResolvedReferenceType extendedInterface = interfaceDeclaration.getAllInterfacesExtended().get(0);
+
+            assertEquals("java.lang.Comparable", extendedInterface.getQualifiedName());
+        } finally {
+            StaticJavaParser.setConfiguration(new ParserConfiguration());
+        }
+    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/Issue257.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/Issue257.java
deleted file mode 100644
index 460b516..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/Issue257.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.github.javaparser.symbolsolver.javassistmodel;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.symbolsolver.AbstractTest;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-public class Issue257 extends AbstractTest {
-
-    private TypeSolver typeSolver;
-
-    @Before
-    public void setup() throws IOException {
-        String pathToJar = adaptPath("src/test/resources/issue257/issue257.jar");
-        File jar = new File(pathToJar);
-        typeSolver = new CombinedTypeSolver(new JarTypeSolver(jar.getAbsolutePath()), new ReflectionTypeSolver());
-    }
-
-    @Test
-    public void verifyBCanBeSolved() throws FileNotFoundException {
-        typeSolver.solveType("net.testbug.B");
-    }
-
-    @Test
-    public void issue257() throws FileNotFoundException {
-        String pathToSourceFile = adaptPath("src/test/resources/issue257/A.java.txt");
-        CompilationUnit cu = JavaParser.parse(new File(pathToSourceFile));
-        Statement statement = cu.getClassByName("A").get().getMethodsByName("run").get(0).getBody().get().getStatement(0);
-        ExpressionStmt expressionStmt = (ExpressionStmt)statement;
-        Expression expression = expressionStmt.getExpression();
-        JavaParserFacade.get(typeSolver).getType(expression);
-    }
-
-}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/Issue257Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/Issue257Test.java
new file mode 100644
index 0000000..d72d016
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/Issue257Test.java
@@ -0,0 +1,46 @@
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+
+class Issue257Test extends AbstractSymbolResolutionTest {
+
+    private TypeSolver typeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/issue257/issue257.jar");
+        typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
+    }
+
+    @Test
+    void verifyBCanBeSolved() {
+        typeSolver.solveType("net.testbug.B");
+    }
+
+    @Test
+    void issue257() throws IOException {
+        Path pathToSourceFile = adaptPath("src/test/resources/issue257/A.java.txt");
+        CompilationUnit cu = parse(pathToSourceFile);
+        Statement statement = cu.getClassByName("A").get().getMethodsByName("run").get(0).getBody().get().getStatement(0);
+        ExpressionStmt expressionStmt = (ExpressionStmt)statement;
+        Expression expression = expressionStmt.getExpression();
+        JavaParserFacade.get(typeSolver).getType(expression);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java
index 9f55977..5188a43 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclarationTest.java
@@ -16,34 +16,49 @@
 
 package com.github.javaparser.symbolsolver.javassistmodel;
 
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableSet;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class JavassistClassDeclarationTest extends AbstractTest {
+class JavassistClassDeclarationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver;
 
     private TypeSolver newTypeSolver;
 
-    @Before
-    public void setup() throws IOException {
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+    private TypeSolver anotherTypeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
 
-        String newPathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
+        Path newPathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
         newTypeSolver = new CombinedTypeSolver(new JarTypeSolver(newPathToJar), new ReflectionTypeSolver());
+
+        Path anotherPathToJar = adaptPath("src/test/resources/test-artifact-1.0.0.jar");
+        anotherTypeSolver = new CombinedTypeSolver(new JarTypeSolver(anotherPathToJar), new ReflectionTypeSolver());
     }
 
     ///
@@ -51,145 +66,219 @@
     ///
 
     @Test
-    public void testIsClass() {
+    void testIsClass() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(true, compilationUnit.isClass());
+        assertTrue(compilationUnit.isClass());
     }
 
     @Test
-    public void testIsInterface() {
+    void testIsInterface() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(false, compilationUnit.isInterface());
+        assertFalse(compilationUnit.isInterface());
     }
 
     @Test
-    public void testIsEnum() {
+    void testIsEnum() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(false, compilationUnit.isEnum());
+        assertFalse(compilationUnit.isEnum());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(false, compilationUnit.isTypeParameter());
+        assertFalse(compilationUnit.isTypeParameter());
     }
 
     @Test
-    public void testIsType() {
+    void testIsType() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(true, compilationUnit.isType());
+        assertTrue(compilationUnit.isType());
     }
 
     @Test
-    public void testAsType() {
+    void testAsType() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(compilationUnit, compilationUnit.asType());
     }
 
     @Test
-    public void testAsClass() {
+    void testAsClass() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(compilationUnit, compilationUnit.asClass());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsInterface() {
-        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
+    @Test
+    void testAsInterface() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         compilationUnit.asInterface();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsEnum() {
-        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        compilationUnit.asEnum();
-    }
+    });
+}
 
     @Test
-    public void testGetPackageName() {
+    void testAsEnum() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
+        compilationUnit.asEnum();
+    });
+}
+
+    @Test
+    void testGetPackageName() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast", compilationUnit.getPackageName());
     }
 
     @Test
-    public void testGetClassName() {
+    void testGetClassName() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("CompilationUnit", compilationUnit.getClassName());
     }
 
     @Test
-    public void testGetQualifiedName() {
+    void testGetQualifiedName() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast.CompilationUnit", compilationUnit.getQualifiedName());
     }
 
+    @Test
+    void testHasDirectlyAnnotation() {
+        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.TestClass");
+        assertTrue(compilationUnit.hasDirectlyAnnotation("com.github.javaparser.test.TestAnnotation"));
+    }
+
+    @Test
+    void testHasAnnotation() {
+        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.TestChildClass");
+        assertTrue(compilationUnit.hasAnnotation("com.github.javaparser.test.TestAnnotation"));
+    }
+
+    @Test
+    void testGetGenericTypeField(){
+        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.ClassWithFields");
+        List<ResolvedFieldDeclaration> declarationList = compilationUnit.getAllFields();
+        assertEquals(6, declarationList.size());
+
+        Map<String, ResolvedType> fields = new HashMap<>();
+        for (ResolvedFieldDeclaration fieldDeclaration : declarationList) {
+            String name = fieldDeclaration.getName();
+            ResolvedType type = fieldDeclaration.getType();
+            fields.put(name, type);
+        }
+
+        assertTrue(fields.containsKey("genericParamObjectField"));
+        assertTrue(fields.containsKey("genericPrimitiveArrayField"));
+        assertTrue(fields.containsKey("genericObjectArrayField"));
+        assertTrue(fields.containsKey("genericField"));
+        assertTrue(fields.containsKey("primitiveField"));
+        assertTrue(fields.containsKey("objectField"));
+    }
+
+    @Test
+    void testGetDeclaredMethods() {
+        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.Position");
+        Set<ResolvedMethodDeclaration> methodsSet = compilationUnit.getDeclaredMethods();
+        assertEquals(12, methodsSet.size());
+
+        Map<String, MethodUsage> methods = new HashMap<>();
+        for (ResolvedMethodDeclaration method : methodsSet) {
+            methods.put(method.getName(), new MethodUsage(method));
+        }
+
+        assertTrue(methods.containsKey("pos"));
+        assertEquals(2, methods.get("pos").getNoParams());
+        assertTrue(methods.containsKey("withColumn"));
+        assertEquals(1, methods.get("withColumn").getNoParams());
+        assertTrue(methods.containsKey("withLine"));
+        assertEquals(1, methods.get("withLine").getNoParams());
+        assertTrue(methods.containsKey("valid"));
+        assertEquals(0, methods.get("valid").getNoParams());
+        assertTrue(methods.containsKey("invalid"));
+        assertEquals(0, methods.get("invalid").getNoParams());
+        assertTrue(methods.containsKey("orIfInvalid"));
+        assertEquals(1, methods.get("orIfInvalid").getNoParams());
+        assertTrue(methods.containsKey("isAfter"));
+        assertEquals(1, methods.get("isAfter").getNoParams());
+        assertTrue(methods.containsKey("isBefore"));
+        assertEquals(1, methods.get("isBefore").getNoParams());
+        assertTrue(methods.containsKey("compareTo"));
+        assertEquals(1, methods.get("compareTo").getNoParams());
+        assertTrue(methods.containsKey("equals"));
+        assertEquals(1, methods.get("equals").getNoParams());
+        assertTrue(methods.containsKey("hashCode"));
+        assertEquals(0, methods.get("hashCode").getNoParams());
+        assertTrue(methods.containsKey("toString"));
+        assertEquals(0, methods.get("toString").getNoParams());
+    }
+
     ///
     /// Test ancestors
     ///
 
     @Test
-    public void testGetSuperclass() {
+    void testGetSuperclass() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
     }
 
     @Test
-    public void testGetSuperclassWithoutTypeParameters() {
+    void testGetSuperclassWithoutTypeParameters() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
     }
 
     @Test
-    public void testGetSuperclassWithTypeParameters() {
+    void testGetSuperclassWithTypeParameters() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", compilationUnit.getSuperClass().getQualifiedName());
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", compilationUnit.getSuperClass().typeParametersMap().getValueBySignature("com.github.javaparser.ast.body.BodyDeclaration.T").get().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void testGetAllSuperclasses() {
+    void testGetAllSuperclasses() {
         JavassistClassDeclaration cu = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllAncestors() {
+    void testGetAllAncestors() {
         JavassistClassDeclaration cu = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllAncestors().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllAncestors().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetInterfaces() {
+    void testGetInterfaces() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
 
         JavassistClassDeclaration coid = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.DocumentableNode"), coid.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("com.github.javaparser.ast.DocumentableNode"), coid.getInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllInterfaces() {
+    void testGetAllInterfaces() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of(), compilationUnit.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of(), compilationUnit.getAllInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
 
         JavassistClassDeclaration coid = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.NamedNode", "com.github.javaparser.ast.body.AnnotableNode", "com.github.javaparser.ast.DocumentableNode"), coid.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("com.github.javaparser.ast.NamedNode", "com.github.javaparser.ast.body.AnnotableNode", "com.github.javaparser.ast.DocumentableNode"), coid.getAllInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllSuperclassesWithoutTypeParameters() {
+    void testGetAllSuperclassesWithoutTypeParameters() {
         JavassistClassDeclaration cu = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllSuperclassesWithTypeParameters() {
+    void testGetAllSuperclassesWithTypeParameters() {
         JavassistClassDeclaration constructorDeclaration = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(3, constructorDeclaration.getAllSuperClasses().size());
-        assertEquals(true, constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.body.BodyDeclaration")));
-        assertEquals(true, constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.Node")));
-        assertEquals(true, constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("java.lang.Object")));
+        assertTrue(constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.body.BodyDeclaration")));
+        assertTrue(constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.Node")));
+        assertTrue(constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("java.lang.Object")));
 
-        ResolvedReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAllSuperClasses().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -203,20 +292,20 @@
     }
 
     @Test
-    public void testGetInterfacesWithoutParameters() {
+    void testGetInterfacesWithoutParameters() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
 
         JavassistClassDeclaration coid = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
-        assertEquals(ImmutableSet.of("com.github.javaparser.ast.nodeTypes.NodeWithExtends", "com.github.javaparser.ast.nodeTypes.NodeWithImplements"), coid.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("com.github.javaparser.ast.nodeTypes.NodeWithExtends", "com.github.javaparser.ast.nodeTypes.NodeWithImplements"), coid.getInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetInterfacesWithParameters() {
+    void testGetInterfacesWithParameters() {
         JavassistClassDeclaration constructorDeclaration = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(7, constructorDeclaration.getInterfaces().size());
 
-        ResolvedReferenceType interfaze = null;
+        ResolvedReferenceType interfaze;
 
         interfaze = constructorDeclaration.getInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -247,9 +336,9 @@
     }
 
     @Test
-    public void testGetAllInterfacesWithoutParameters() {
+    void testGetAllInterfacesWithoutParameters() {
         JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of("java.lang.Cloneable"), compilationUnit.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("java.lang.Cloneable"), compilationUnit.getAllInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
 
         JavassistClassDeclaration coid = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ClassOrInterfaceDeclaration");
         assertEquals(ImmutableSet.of("com.github.javaparser.ast.nodeTypes.NodeWithExtends",
@@ -259,15 +348,15 @@
                 "com.github.javaparser.ast.nodeTypes.NodeWithName",
                 "com.github.javaparser.ast.nodeTypes.NodeWithModifiers",
                 "com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc",
-                "com.github.javaparser.ast.nodeTypes.NodeWithMembers"), coid.getAllInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+                "com.github.javaparser.ast.nodeTypes.NodeWithMembers"), coid.getAllInterfaces().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllInterfacesWithParameters() {
+    void testGetAllInterfacesWithParameters() {
         JavassistClassDeclaration constructorDeclaration = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(9, constructorDeclaration.getAllInterfaces().size());
 
-        ResolvedReferenceType interfaze = null;
+        ResolvedReferenceType interfaze;
 
         interfaze = constructorDeclaration.getAllInterfaces().get(0);
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithJavaDoc", interfaze.getQualifiedName());
@@ -305,11 +394,11 @@
     }
 
     @Test
-    public void testGetAncestorsWithTypeParameters() {
+    void testGetAncestorsWithTypeParameters() {
         JavassistClassDeclaration constructorDeclaration = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(8, constructorDeclaration.getAncestors().size());
 
-        ResolvedReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -344,17 +433,17 @@
     }
 
     @Test
-    public void testGetAllAncestorsWithoutTypeParameters() {
+    void testGetAllAncestorsWithoutTypeParameters() {
         JavassistClassDeclaration cu = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.CompilationUnit");
-        assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllAncestors().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
+        assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllAncestors().stream().map(ResolvedReferenceType::getQualifiedName).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllAncestorsWithTypeParameters() {
+    void testGetAllAncestorsWithTypeParameters() {
         JavassistClassDeclaration constructorDeclaration = (JavassistClassDeclaration) newTypeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(12, constructorDeclaration.getAllAncestors().size());
 
-        ResolvedReferenceType ancestor = null;
+        ResolvedReferenceType ancestor;
 
         ancestor = constructorDeclaration.getAllAncestors().get(0);
         assertEquals("com.github.javaparser.ast.body.BodyDeclaration", ancestor.getQualifiedName());
@@ -400,5 +489,5 @@
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithBlockStmt", ancestor.getQualifiedName());
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", ancestor.typeParametersMap().getValueBySignature("com.github.javaparser.ast.nodeTypes.NodeWithBlockStmt.T").get().asReferenceType().getQualifiedName());
     }
-    
+
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclarationTest.java
index 8e6d66f..6ed3e25 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclarationTest.java
@@ -17,26 +17,34 @@
 package com.github.javaparser.symbolsolver.javassistmodel;
 
 import com.github.javaparser.resolution.declarations.ResolvedEnumDeclaration;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class JavassistEnumDeclarationTest extends AbstractTest {
+class JavassistEnumDeclarationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() throws IOException {
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
+    private TypeSolver anotherTypeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
         typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
+
+        Path anotherPathToJar = adaptPath("src/test/resources/test-artifact-1.0.0.jar");
+        anotherTypeSolver = new CombinedTypeSolver(new JarTypeSolver(anotherPathToJar), new ReflectionTypeSolver());
     }
 
     ///
@@ -44,77 +52,93 @@
     ///
 
     @Test
-    public void testIsClass() {
+    void testIsClass() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(false, modifier.isClass());
     }
 
     @Test
-    public void testIsInterface() {
+    void testIsInterface() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(false, modifier.isInterface());
     }
 
     @Test
-    public void testIsEnum() {
+    void testIsEnum() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(true, modifier.isEnum());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(false, modifier.isTypeParameter());
     }
 
     @Test
-    public void testIsType() {
+    void testIsType() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(true, modifier.isType());
     }
 
     @Test
-    public void testAsType() {
+    void testAsType() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(modifier, modifier.asType());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsClass() {
-        ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    @Test
+    void testAsClass() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         modifier.asClass();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsInterface() {
-        ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        modifier.asInterface();
-    }
+    });
+}
 
     @Test
-    public void testAsEnum() {
+    void testAsInterface() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+        modifier.asInterface();
+    });
+}
+
+    @Test
+    void testAsEnum() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals(modifier, modifier.asEnum());
     }
 
     @Test
-    public void testGetPackageName() {
+    void testGetPackageName() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals("com.github.javaparser.ast", modifier.getPackageName());
     }
 
     @Test
-    public void testGetClassName() {
+    void testGetClassName() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals("Modifier", modifier.getClassName());
     }
 
     @Test
-    public void testGetQualifiedName() {
+    void testGetQualifiedName() {
         ResolvedEnumDeclaration modifier = (ResolvedEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
         assertEquals("com.github.javaparser.ast.Modifier", modifier.getQualifiedName());
     }
 
+    @Test
+    void testHasDirectlyAnnotation(){
+        ResolvedEnumDeclaration compilationUnit = (ResolvedEnumDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.TestEnum");
+        assertTrue(compilationUnit.hasDirectlyAnnotation("com.github.javaparser.test.TestAnnotation"));
+    }
+
+    @Test
+    void testHasAnnotation(){
+        ResolvedEnumDeclaration compilationUnit = (ResolvedEnumDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.TestParentEnum");
+        assertTrue(compilationUnit.hasAnnotation("com.github.javaparser.test.TestAnnotation"));
+    }
+
     ///
     /// Test ancestors
     ///
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java
index a593ec4..770e30b 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java
@@ -16,26 +16,34 @@
 
 package com.github.javaparser.symbolsolver.javassistmodel;
 
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class JavassistInterfaceDeclarationTest extends AbstractTest {
+class JavassistInterfaceDeclarationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() throws IOException {
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
+    private TypeSolver anotherTypeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
         typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
+
+        Path anotherPathToJar = adaptPath("src/test/resources/test-artifact-1.0.0.jar");
+        anotherTypeSolver = new CombinedTypeSolver(new JarTypeSolver(anotherPathToJar), new ReflectionTypeSolver());
     }
 
     ///
@@ -43,79 +51,94 @@
     ///
 
     @Test
-    public void testIsClass() {
+    void testIsClass() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(false, nodeWithAnnotations.isClass());
     }
 
     @Test
-    public void testIsInterface() {
+    void testIsInterface() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(true, nodeWithAnnotations.isInterface());
     }
 
     @Test
-    public void testIsEnum() {
+    void testIsEnum() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(false, nodeWithAnnotations.isEnum());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(false, nodeWithAnnotations.isTypeParameter());
     }
 
     @Test
-    public void testIsType() {
+    void testIsType() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(true, nodeWithAnnotations.isType());
     }
 
     @Test
-    public void testAsType() {
+    void testAsType() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(nodeWithAnnotations, nodeWithAnnotations.asType());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsClass() {
-        JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
+    @Test
+    void testAsClass() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         nodeWithAnnotations.asClass();
-    }
+    });
+}
 
     @Test
-    public void testAsInterface() {
+    void testAsInterface() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals(nodeWithAnnotations, nodeWithAnnotations.asInterface());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsEnum() {
-        JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
+    @Test
+    void testAsEnum() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         nodeWithAnnotations.asEnum();
-    }
+    });
+}
 
     @Test
-    public void testGetPackageName() {
+    void testGetPackageName() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals("com.github.javaparser.ast.nodeTypes", nodeWithAnnotations.getPackageName());
     }
 
     @Test
-    public void testGetClassName() {
+    void testGetClassName() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals("NodeWithAnnotations", nodeWithAnnotations.getClassName());
     }
 
     @Test
-    public void testGetQualifiedName() {
+    void testGetQualifiedName() {
         JavassistInterfaceDeclaration nodeWithAnnotations = (JavassistInterfaceDeclaration) typeSolver.solveType("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations");
         assertEquals("com.github.javaparser.ast.nodeTypes.NodeWithAnnotations", nodeWithAnnotations.getQualifiedName());
     }
 
+    @Test
+    void testHasDirectlyAnnotation(){
+        JavassistInterfaceDeclaration compilationUnit = (JavassistInterfaceDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.TestInterface");
+        assertTrue(compilationUnit.hasDirectlyAnnotation("com.github.javaparser.test.TestAnnotation"));
+    }
+
+    @Test
+    void testHasAnnotation(){
+        JavassistInterfaceDeclaration compilationUnit = (JavassistInterfaceDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.TestChildInterface");
+        assertTrue(compilationUnit.hasAnnotation("com.github.javaparser.test.TestAnnotation"));
+    }
+
     ///
     /// Test ancestors
     ///
-
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclarationTest.java
new file mode 100644
index 0000000..71078ce
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclarationTest.java
@@ -0,0 +1,72 @@
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.resolution.declarations.ResolvedParameterDeclaration;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+public class JavassistMethodDeclarationTest extends AbstractSymbolResolutionTest {
+
+    private TypeSolver typeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javassistmethoddecl/javassistmethoddecl.jar");
+        typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
+    }
+
+    @Test
+    void getParam_forMethodParameterWithRawType() {
+        JavassistClassDeclaration classDecl = (JavassistClassDeclaration) typeSolver.solveType("C");
+        JavassistMethodDeclaration method = findMethodWithName(classDecl, "methodWithRawParameter");
+
+        ResolvedParameterDeclaration param = method.getParam(0);
+
+        assertThat(param.describeType(), is("java.util.List"));
+    }
+
+    @Test
+    void getParam_forMethodParameterWithGenericType() {
+        JavassistClassDeclaration classDecl = (JavassistClassDeclaration) typeSolver.solveType("C");
+        JavassistMethodDeclaration method = findMethodWithName(classDecl, "methodWithGenericParameter");
+
+        ResolvedParameterDeclaration param = method.getParam(0);
+
+        assertThat(param.describeType(), is("java.util.List<java.lang.String>"));
+    }
+
+    @Test
+    void getParam_forMethodParameterWithTypeParameter() {
+        JavassistClassDeclaration classDecl = (JavassistClassDeclaration) typeSolver.solveType("C");
+        JavassistMethodDeclaration method = findMethodWithName(classDecl, "methodWithTypeParameter");
+
+        ResolvedParameterDeclaration param = method.getParam(0);
+
+        assertThat(param.describeType(), is("java.util.List<S>"));
+    }
+
+    @Test
+    void getParam_forGenericMethodWithTypeParameter() {
+        JavassistClassDeclaration classDecl = (JavassistClassDeclaration) typeSolver.solveType("C");
+        JavassistMethodDeclaration method = findMethodWithName(classDecl, "genericMethodWithTypeParameter");
+
+        ResolvedParameterDeclaration param = method.getParam(0);
+
+        assertThat(param.describeType(), is("java.util.List<T>"));
+    }
+
+    private JavassistMethodDeclaration findMethodWithName(JavassistClassDeclaration classDecl, String name) {
+        return classDecl.getDeclaredMethods().stream().filter(methodDecl -> methodDecl.getName().equals(name))
+                .map(m -> (JavassistMethodDeclaration) m).findAny().get();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclarationTest.java
new file mode 100644
index 0000000..f96edb0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclarationTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.symbolsolver.javassistmodel;
+
+import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class JavassistParameterDeclarationTest extends AbstractResolutionTest {
+
+    private TypeSolver typeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
+        typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
+    }
+
+    @Test
+    void noNamesAvailableInInterfaceMethods() {
+        JavassistInterfaceDeclaration namesNotAvailable = (JavassistInterfaceDeclaration) typeSolver
+                .solveType("com.github.javaparser.ast.nodeTypes.NodeWithBody");
+
+        namesNotAvailable.getDeclaredMethods().forEach(methodDecl -> {
+            for (int i = 0; i < methodDecl.getNumberOfParams(); i++) {
+                assertFalse(methodDecl.getParam(i).hasName());
+                assertNull(methodDecl.getParam(i).getName());
+            }
+        });
+    }
+
+    @Test
+    void nameForConstructorParameter() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        ResolvedConstructorDeclaration constructor = rangeDecl.getConstructors().get(0);
+        assertEquals("begin", constructor.getParam(0).getName());
+        assertTrue(constructor.getParam(0).hasName());
+        assertEquals("end", constructor.getParam(1).getName());
+        assertTrue(constructor.getParam(1).hasName());
+    }
+
+    @Test
+    void nameForMethodParameters() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        for (ResolvedMethodDeclaration methodDecl : rangeDecl.getDeclaredMethods()) {
+            switch (methodDecl.getName()) {
+                case "range": // static methods
+                    if (methodDecl.getNumberOfParams() == 2) {
+                        assertEquals("begin", methodDecl.getParam(0).getName());
+                        assertTrue(methodDecl.getParam(0).hasName());
+                        assertEquals("end", methodDecl.getParam(1).getName());
+                        assertTrue(methodDecl.getParam(1).hasName());
+                    } else if (methodDecl.getNumberOfParams() == 4) {
+                        assertEquals("beginLine", methodDecl.getParam(0).getName());
+                        assertTrue(methodDecl.getParam(0).hasName());
+                        assertEquals("beginColumn", methodDecl.getParam(1).getName());
+                        assertTrue(methodDecl.getParam(1).hasName());
+                        assertEquals("endLine", methodDecl.getParam(2).getName());
+                        assertTrue(methodDecl.getParam(2).hasName());
+                        assertEquals("endColumn", methodDecl.getParam(3).getName());
+                        assertTrue(methodDecl.getParam(3).hasName());
+                    }
+                    break;
+                case "withBeginColumn":
+                    assertEquals("column", methodDecl.getParam(0).getName());
+                    assertTrue(methodDecl.getParam(0).hasName());
+                    break;
+            }
+        }
+    }
+
+    @Test
+    void isField() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        JavassistParameterDeclaration paramDecl = (JavassistParameterDeclaration) rangeDecl.getConstructors().get(0).getParam(0);
+
+        assertFalse(paramDecl.isField());
+    }
+
+    @Test
+    void isParameter() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        JavassistParameterDeclaration paramDecl = (JavassistParameterDeclaration) rangeDecl.getConstructors().get(0).getParam(0);
+
+        assertTrue(paramDecl.isParameter());
+    }
+
+
+    @Test
+    void isType() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        JavassistParameterDeclaration paramDecl = (JavassistParameterDeclaration) rangeDecl.getConstructors().get(0).getParam(0);
+
+        assertFalse(paramDecl.isType());
+    }
+
+    @Test
+    void isVaraidic() {
+        JavassistClassDeclaration cuDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github" +
+                ".javaparser" +
+                ".ast.CompilationUnit");
+        cuDecl.getDeclaredMethods().forEach(methodDecl -> {
+            if ("addClass".equals(methodDecl.getName())) {
+                if (methodDecl.getNumberOfParams() == 1) {
+                    assertFalse(methodDecl.getParam(0).isVariadic());
+                } else if (methodDecl.getNumberOfParams() == 2) {
+                    assertFalse(methodDecl.getParam(0).isVariadic());
+                    assertTrue(methodDecl.getParam(1).isVariadic());
+                }
+            }
+        });
+    }
+
+    @Test
+    void isEnumConstant() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        JavassistParameterDeclaration paramDecl = (JavassistParameterDeclaration) rangeDecl.getConstructors().get(0).getParam(0);
+
+        assertFalse(paramDecl.isEnumConstant());
+    }
+
+    @Test
+    void isMethod() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        JavassistParameterDeclaration paramDecl = (JavassistParameterDeclaration) rangeDecl.getConstructors().get(0).getParam(0);
+
+        assertFalse(paramDecl.isMethod());
+    }
+
+
+    @Test
+    void isVariable() {
+        JavassistClassDeclaration rangeDecl = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.Range");
+        JavassistParameterDeclaration paramDecl = (JavassistParameterDeclaration) rangeDecl.getConstructors().get(0).getParam(0);
+
+        assertFalse(paramDecl.isVariable());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameterDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameterDeclarationTest.java
new file mode 100644
index 0000000..22201b2
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameterDeclarationTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JavassistTypeParameterDeclarationTest  extends AbstractResolutionTest {
+
+    private TypeSolver typeSolver;
+
+    @BeforeEach
+    void setup() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar");
+        typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
+    }
+
+    @Test
+    void testGetBounds() {
+        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("com.github.javaparser.utils.PositionUtils");
+        assertTrue(compilationUnit.isClass());
+
+        for (ResolvedMethodDeclaration method : compilationUnit.getDeclaredMethods()) {
+            switch (method.getName()) {
+                case "sortByBeginPosition":
+                    List<ResolvedTypeParameterDeclaration> typeParams =  method.getTypeParameters();
+                    assertEquals(1, typeParams.size());
+                    assertEquals("T", typeParams.get(0).getName());
+
+                    List<ResolvedTypeParameterDeclaration.Bound> bounds = typeParams.get(0).getBounds();
+                    assertEquals(1, bounds.size());
+                    assertTrue(bounds.get(0).isExtends());
+                    assertEquals("com.github.javaparser.ast.Node", bounds.get(0).getType().describe());
+            }
+        }
+    }
+
+    @Test
+    void testGetComplexBounds() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javassist_generics/generics.jar");
+        typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver());
+
+        JavassistClassDeclaration compilationUnit = (JavassistClassDeclaration) typeSolver.solveType("javaparser.GenericClass");
+        assertTrue(compilationUnit.isClass());
+
+        for (ResolvedMethodDeclaration method : compilationUnit.getDeclaredMethods()) {
+            if ("complexGenerics".equals(method.getName())) {
+                List<ResolvedTypeParameterDeclaration> typeParams =  method.getTypeParameters();
+
+                assertEquals(1, typeParams.size());
+                assertEquals("T", typeParams.get(0).getName());
+
+                List<ResolvedTypeParameterDeclaration.Bound> bounds = typeParams.get(0).getBounds();
+                assertEquals(2, bounds.size());
+                assertTrue(bounds.get(0).isExtends());
+                assertEquals("java.lang.Object", bounds.get(0).getType().describe());
+                assertTrue(bounds.get(1).isExtends());
+                assertEquals("javaparser.GenericClass.Foo<? extends T>", bounds.get(1).getType().describe());
+            }
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java
index bda2cc9..86f42bd 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java
@@ -22,24 +22,24 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.function.Consumer;
 import java.util.function.Function;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class FunctionInterfaceLogicTest {
+class FunctionInterfaceLogicTest {
 
     @Test
-    public void testGetFunctionalMethodNegativeCaseOnClass() {
+    void testGetFunctionalMethodNegativeCaseOnClass() {
         TypeSolver typeSolver = new ReflectionTypeSolver();
         ResolvedType string = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
         assertEquals(false, FunctionalInterfaceLogic.getFunctionalMethod(string).isPresent());
     }
 
     @Test
-    public void testGetFunctionalMethodPositiveCasesOnInterfaces() {
+    void testGetFunctionalMethodPositiveCasesOnInterfaces() {
         TypeSolver typeSolver = new ReflectionTypeSolver();
         ResolvedType function = new ReferenceTypeImpl(new ReflectionInterfaceDeclaration(Function.class, typeSolver), typeSolver);
         assertEquals(true, FunctionalInterfaceLogic.getFunctionalMethod(function).isPresent());
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/InferenceContextTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/InferenceContextTest.java
index 3af207f..24576b9 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/InferenceContextTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/InferenceContextTest.java
@@ -27,19 +27,19 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.List;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 /**
  * @author Federico Tomassetti
  */
-public class InferenceContextTest {
+class InferenceContextTest {
 
     private TypeSolver typeSolver;
     private ResolvedReferenceType string;
@@ -48,8 +48,8 @@
     private ResolvedReferenceType listOfE;
     private ResolvedTypeParameterDeclaration tpE;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
         string = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
         object = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
@@ -65,19 +65,19 @@
     }
 
     @Test
-    public void noVariablesArePlacedWhenNotNeeded() {
+    void noVariablesArePlacedWhenNotNeeded() {
         ResolvedType result = new InferenceContext(MyObjectProvider.INSTANCE).addPair(object, string);
         assertEquals(object, result);
     }
 
     @Test
-    public void placingASingleVariableTopLevel() {
+    void placingASingleVariableTopLevel() {
         ResolvedType result = new InferenceContext(MyObjectProvider.INSTANCE).addPair(new ResolvedTypeVariable(tpE), listOfString);
         assertEquals(new InferenceVariableType(0, MyObjectProvider.INSTANCE), result);
     }
 
     @Test
-    public void placingASingleVariableInside() {
+    void placingASingleVariableInside() {
         ResolvedType result = new InferenceContext(MyObjectProvider.INSTANCE).addPair(listOfE, listOfString);
         assertEquals(listOf(new InferenceVariableType(0, MyObjectProvider.INSTANCE)), result);
     }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ArrayTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ArrayTypeTest.java
index 1d8e4dd..d1deadd 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ArrayTypeTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ArrayTypeTest.java
@@ -26,16 +26,15 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
 import java.util.List;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class ArrayTypeTest {
+class ArrayTypeTest {
 
     private ResolvedArrayType arrayOfBooleans;
     private ResolvedArrayType arrayOfStrings;
@@ -46,8 +45,8 @@
     private TypeSolver typeSolver;
     private ResolvedTypeParameterDeclaration tpA;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
         OBJECT = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
         STRING = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
@@ -63,84 +62,84 @@
     }
 
     @Test
-    public void testIsArray() {
+    void testIsArray() {
         assertEquals(true, arrayOfBooleans.isArray());
         assertEquals(true, arrayOfStrings.isArray());
     }
 
     @Test
-    public void testIsPrimitive() {
+    void testIsPrimitive() {
         assertEquals(false, arrayOfBooleans.isPrimitive());
         assertEquals(false, arrayOfStrings.isPrimitive());
     }
 
     @Test
-    public void testIsNull() {
+    void testIsNull() {
         assertEquals(false, arrayOfBooleans.isNull());
         assertEquals(false, arrayOfStrings.isNull());
     }
 
     @Test
-    public void testIsReference() {
+    void testIsReference() {
         assertEquals(true, arrayOfBooleans.isReference());
         assertEquals(true, arrayOfStrings.isReference());
     }
 
     @Test
-    public void testIsReferenceType() {
+    void testIsReferenceType() {
         assertEquals(false, arrayOfBooleans.isReferenceType());
         assertEquals(false, arrayOfStrings.isReferenceType());
     }
 
     @Test
-    public void testIsVoid() {
+    void testIsVoid() {
         assertEquals(false, arrayOfBooleans.isVoid());
         assertEquals(false, arrayOfStrings.isVoid());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         assertEquals(false, arrayOfBooleans.isTypeVariable());
         assertEquals(false, arrayOfStrings.isTypeVariable());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsReferenceTypeUsage() {
-        arrayOfBooleans.asReferenceType();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsTypeParameter() {
-        arrayOfBooleans.asTypeParameter();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsPrimitive() {
-        arrayOfBooleans.asPrimitive();
+    @Test
+    void testAsReferenceTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> arrayOfBooleans.asReferenceType());
     }
 
     @Test
-    public void testAsArrayTypeUsage() {
-        assertTrue(arrayOfBooleans == arrayOfBooleans.asArrayType());
-        assertTrue(arrayOfStrings == arrayOfStrings.asArrayType());
-        assertTrue(arrayOfListOfA == arrayOfListOfA.asArrayType());
+    void testAsTypeParameter() {
+        assertThrows(UnsupportedOperationException.class, () -> arrayOfBooleans.asTypeParameter());
     }
 
     @Test
-    public void testAsDescribe() {
+    void testAsPrimitive() {
+        assertThrows(UnsupportedOperationException.class, () -> arrayOfBooleans.asPrimitive());
+    }
+
+    @Test
+    void testAsArrayTypeUsage() {
+        assertSame(arrayOfBooleans, arrayOfBooleans.asArrayType());
+        assertSame(arrayOfStrings, arrayOfStrings.asArrayType());
+        assertSame(arrayOfListOfA, arrayOfListOfA.asArrayType());
+    }
+
+    @Test
+    void testAsDescribe() {
         assertEquals("boolean[]", arrayOfBooleans.describe());
         assertEquals("java.lang.String[]", arrayOfStrings.describe());
     }
 
     @Test
-    public void testReplaceParam() {
-        assertTrue(arrayOfBooleans == arrayOfBooleans.replaceTypeVariables(tpA, OBJECT));
-        assertTrue(arrayOfStrings == arrayOfStrings.replaceTypeVariables(tpA, OBJECT));
+    void testReplaceParam() {
+        assertSame(arrayOfBooleans, arrayOfBooleans.replaceTypeVariables(tpA, OBJECT));
+        assertSame(arrayOfStrings, arrayOfStrings.replaceTypeVariables(tpA, OBJECT));
         assertEquals(arrayOfListOfStrings, arrayOfListOfStrings.replaceTypeVariables(tpA, OBJECT));
         ResolvedArrayType arrayOfListOfObjects = new ResolvedArrayType(new ReferenceTypeImpl(
                 new ReflectionInterfaceDeclaration(List.class, typeSolver),
                 ImmutableList.of(OBJECT), typeSolver));
-        assertEquals(true, arrayOfListOfA.replaceTypeVariables(tpA, OBJECT).isArray());
+        assertTrue(arrayOfListOfA.replaceTypeVariables(tpA, OBJECT).isArray());
         assertEquals(ImmutableList.of(OBJECT),
                 arrayOfListOfA.replaceTypeVariables(tpA, OBJECT).asArrayType().getComponentType()
                         .asReferenceType().typeParametersValues());
@@ -153,11 +152,11 @@
                 arrayOfListOfA.replaceTypeVariables(tpA, OBJECT).asArrayType().getComponentType());
         assertEquals(arrayOfListOfObjects, arrayOfListOfA.replaceTypeVariables(tpA, OBJECT));
         assertEquals(arrayOfListOfStrings, arrayOfListOfA.replaceTypeVariables(tpA, STRING));
-        assertTrue(arrayOfListOfA != arrayOfListOfA.replaceTypeVariables(tpA, OBJECT));
+        assertNotSame(arrayOfListOfA, arrayOfListOfA.replaceTypeVariables(tpA, OBJECT));
     }
 
     @Test
-    public void testIsAssignableBy() {
+    void testIsAssignableBy() {
         assertEquals(false, arrayOfBooleans.isAssignableBy(OBJECT));
         assertEquals(false, arrayOfBooleans.isAssignableBy(STRING));
         assertEquals(false, arrayOfBooleans.isAssignableBy(ResolvedPrimitiveType.BOOLEAN));
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/NullTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/NullTypeTest.java
index 4df2460..677392e 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/NullTypeTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/NullTypeTest.java
@@ -26,15 +26,16 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
 import java.util.List;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class NullTypeTest {
+class NullTypeTest {
 
     private ResolvedArrayType arrayOfBooleans;
     private ResolvedArrayType arrayOfListOfA;
@@ -42,8 +43,8 @@
     private ReferenceTypeImpl STRING;
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
         OBJECT = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
         STRING = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
@@ -54,62 +55,62 @@
     }
 
     @Test
-    public void testIsArray() {
+    void testIsArray() {
         assertEquals(false, NullType.INSTANCE.isArray());
     }
 
     @Test
-    public void testIsPrimitive() {
+    void testIsPrimitive() {
         assertEquals(false, NullType.INSTANCE.isPrimitive());
     }
 
     @Test
-    public void testIsNull() {
+    void testIsNull() {
         assertEquals(true, NullType.INSTANCE.isNull());
     }
 
     @Test
-    public void testIsReference() {
+    void testIsReference() {
         assertEquals(true, NullType.INSTANCE.isReference());
     }
 
     @Test
-    public void testIsReferenceType() {
+    void testIsReferenceType() {
         assertEquals(false, NullType.INSTANCE.isReferenceType());
     }
 
     @Test
-    public void testIsVoid() {
+    void testIsVoid() {
         assertEquals(false, NullType.INSTANCE.isVoid());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         assertEquals(false, NullType.INSTANCE.isTypeVariable());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsReferenceTypeUsage() {
-        NullType.INSTANCE.asReferenceType();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsTypeParameter() {
-        NullType.INSTANCE.asTypeParameter();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsArrayTypeUsage() {
-        NullType.INSTANCE.asArrayType();
+    @Test
+    void testAsReferenceTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> NullType.INSTANCE.asReferenceType());
     }
 
     @Test
-    public void testAsDescribe() {
+    void testAsTypeParameter() {
+        assertThrows(UnsupportedOperationException.class, () -> NullType.INSTANCE.asTypeParameter());
+    }
+
+    @Test
+    void testAsArrayTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> NullType.INSTANCE.asArrayType());
+    }
+
+    @Test
+    void testAsDescribe() {
         assertEquals("null", NullType.INSTANCE.describe());
     }
 
     @Test
-    public void testIsAssignableBy() {
+    void testIsAssignableBy() {
         try {
             assertEquals(false, NullType.INSTANCE.isAssignableBy(NullType.INSTANCE));
             fail();
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/PrimitiveTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/PrimitiveTypeTest.java
index 3679dbd..860390a 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/PrimitiveTypeTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/PrimitiveTypeTest.java
@@ -26,15 +26,15 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
 import java.util.List;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class PrimitiveTypeTest {
+class PrimitiveTypeTest {
 
     private ResolvedArrayType arrayOfBooleans;
     private ResolvedArrayType arrayOfListOfA;
@@ -51,8 +51,8 @@
     private ReferenceTypeImpl floatBox;
     private ReferenceTypeImpl doubleBox;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
         OBJECT = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
         STRING = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
@@ -73,56 +73,56 @@
     }
 
     @Test
-    public void testIsArray() {
+    void testIsArray() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(false, ptu.isArray());
         }
     }
 
     @Test
-    public void testIsPrimitive() {
+    void testIsPrimitive() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(true, ptu.isPrimitive());
         }
     }
 
     @Test
-    public void testIsNull() {
+    void testIsNull() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(false, ptu.isNull());
         }
     }
 
     @Test
-    public void testIsReference() {
+    void testIsReference() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(false, ptu.isReference());
         }
     }
 
     @Test
-    public void testIsReferenceType() {
+    void testIsReferenceType() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(false, ptu.isReferenceType());
         }
     }
 
     @Test
-    public void testIsVoid() {
+    void testIsVoid() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(false, ptu.isVoid());
         }
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(false, ptu.isTypeVariable());
         }
     }
 
     @Test
-    public void testAsReferenceTypeUsage() {
+    void testAsReferenceTypeUsage() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             try {
                 ptu.asReferenceType();
@@ -133,7 +133,7 @@
     }
 
     @Test
-    public void testAsTypeParameter() {
+    void testAsTypeParameter() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             try {
                 ptu.asTypeParameter();
@@ -144,7 +144,7 @@
     }
 
     @Test
-    public void testAsArrayTypeUsage() {
+    void testAsArrayTypeUsage() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             try {
                 ptu.asArrayType();
@@ -155,7 +155,7 @@
     }
 
     @Test
-    public void testAsDescribe() {
+    void testAsDescribe() {
         assertEquals("boolean", ResolvedPrimitiveType.BOOLEAN.describe());
         assertEquals("char", ResolvedPrimitiveType.CHAR.describe());
         assertEquals("byte", ResolvedPrimitiveType.BYTE.describe());
@@ -167,7 +167,7 @@
     }
 
     @Test
-    public void testIsAssignableByOtherPrimitiveTypes() {
+    void testIsAssignableByOtherPrimitiveTypes() {
         assertEquals(true, ResolvedPrimitiveType.BOOLEAN.isAssignableBy(ResolvedPrimitiveType.BOOLEAN));
         assertEquals(false, ResolvedPrimitiveType.BOOLEAN.isAssignableBy(ResolvedPrimitiveType.CHAR));
         assertEquals(false, ResolvedPrimitiveType.BOOLEAN.isAssignableBy(ResolvedPrimitiveType.BYTE));
@@ -242,7 +242,7 @@
     }
 
     @Test
-    public void testIsAssignableByBoxedTypes() {
+    void testIsAssignableByBoxedTypes() {
         assertEquals(true, ResolvedPrimitiveType.BOOLEAN.isAssignableBy(booleanBox));
         assertEquals(false, ResolvedPrimitiveType.BOOLEAN.isAssignableBy(characterBox));
         assertEquals(false, ResolvedPrimitiveType.BOOLEAN.isAssignableBy(byteBox));
@@ -317,7 +317,7 @@
     }
 
     @Test
-    public void testIsAssignableByAnythingElse() {
+    void testIsAssignableByAnythingElse() {
         for (ResolvedPrimitiveType ptu : ResolvedPrimitiveType.values()) {
             assertEquals(false, ptu.isAssignableBy(OBJECT));
             assertEquals(false, ptu.isAssignableBy(STRING));
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java
index 3f4b318..55d20db 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeTest.java
@@ -16,26 +16,34 @@
 
 package com.github.javaparser.symbolsolver.model.typesystem;
 
-import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedInterfaceDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
-import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StringProvider;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.*;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.Serializable;
+import java.nio.Buffer;
+import java.nio.CharBuffer;
 import java.util.*;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class ReferenceTypeTest {
+class ReferenceTypeTest {
 
     private ReferenceTypeImpl listOfA;
     private ReferenceTypeImpl listOfStrings;
@@ -47,8 +55,8 @@
     private ReferenceTypeImpl string;
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
         object = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
         string = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
@@ -73,7 +81,7 @@
     }
 
     @Test
-    public void testDerivationOfTypeParameters() {
+    void testDerivationOfTypeParameters() {
         ReflectionTypeSolver typeSolver = new ReflectionTypeSolver();
         ReferenceTypeImpl ref1 = new ReferenceTypeImpl(typeSolver.solveType(LinkedList.class.getCanonicalName()), typeSolver);
         assertEquals(1, ref1.typeParametersValues().size());
@@ -82,7 +90,7 @@
     }
 
     @Test
-    public void testIsArray() {
+    void testIsArray() {
         assertEquals(false, object.isArray());
         assertEquals(false, string.isArray());
         assertEquals(false, listOfA.isArray());
@@ -90,7 +98,7 @@
     }
 
     @Test
-    public void testIsPrimitive() {
+    void testIsPrimitive() {
         assertEquals(false, object.isPrimitive());
         assertEquals(false, string.isPrimitive());
         assertEquals(false, listOfA.isPrimitive());
@@ -98,7 +106,7 @@
     }
 
     @Test
-    public void testIsNull() {
+    void testIsNull() {
         assertEquals(false, object.isNull());
         assertEquals(false, string.isNull());
         assertEquals(false, listOfA.isNull());
@@ -106,7 +114,7 @@
     }
 
     @Test
-    public void testIsReference() {
+    void testIsReference() {
         assertEquals(true, object.isReference());
         assertEquals(true, string.isReference());
         assertEquals(true, listOfA.isReference());
@@ -114,7 +122,7 @@
     }
 
     @Test
-    public void testIsReferenceType() {
+    void testIsReferenceType() {
         assertEquals(true, object.isReferenceType());
         assertEquals(true, string.isReferenceType());
         assertEquals(true, listOfA.isReferenceType());
@@ -122,7 +130,7 @@
     }
 
     @Test
-    public void testIsVoid() {
+    void testIsVoid() {
         assertEquals(false, object.isVoid());
         assertEquals(false, string.isVoid());
         assertEquals(false, listOfA.isVoid());
@@ -130,7 +138,7 @@
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         assertEquals(false, object.isTypeVariable());
         assertEquals(false, string.isTypeVariable());
         assertEquals(false, listOfA.isTypeVariable());
@@ -138,25 +146,25 @@
     }
 
     @Test
-    public void testAsReferenceTypeUsage() {
+    void testAsReferenceTypeUsage() {
         assertTrue(object == object.asReferenceType());
         assertTrue(string == string.asReferenceType());
         assertTrue(listOfA == listOfA.asReferenceType());
         assertTrue(listOfStrings == listOfStrings.asReferenceType());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsTypeParameter() {
-        object.asTypeParameter();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsArrayTypeUsage() {
-        object.asArrayType();
+    @Test
+    void testAsTypeParameter() {
+        assertThrows(UnsupportedOperationException.class, () -> object.asTypeParameter());
     }
 
     @Test
-    public void testAsDescribe() {
+    void testAsArrayTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> object.asArrayType());
+    }
+
+    @Test
+    void testAsDescribe() {
         assertEquals("java.lang.Object", object.describe());
         assertEquals("java.lang.String", string.describe());
         assertEquals("java.util.List<A>", listOfA.describe());
@@ -164,7 +172,7 @@
     }
 
     @Test
-    public void testReplaceParam() {
+    void testReplaceParam() {
         ResolvedTypeParameterDeclaration tpA = ResolvedTypeParameterDeclaration.onType("A", "foo.Bar", Collections.emptyList());
         assertTrue(object == object.replaceTypeVariables(tpA, object));
         assertTrue(string == string.replaceTypeVariables(tpA, object));
@@ -173,7 +181,7 @@
     }
 
     @Test
-    public void testIsAssignableBySimple() {
+    void testIsAssignableBySimple() {
         assertEquals(true, object.isAssignableBy(string));
         assertEquals(false, string.isAssignableBy(object));
         assertEquals(false, listOfStrings.isAssignableBy(listOfA));
@@ -191,7 +199,7 @@
     }
 
     @Test
-    public void testIsAssignableByBoxedPrimitive(){
+    void testIsAssignableByBoxedPrimitive(){
         ResolvedReferenceType numberType = new ReferenceTypeImpl(new ReflectionClassDeclaration(Number.class, typeSolver),typeSolver);
         ResolvedReferenceType intType = new ReferenceTypeImpl(new ReflectionClassDeclaration(Integer.class, typeSolver),typeSolver);
         ResolvedReferenceType doubleType = new ReferenceTypeImpl(new ReflectionClassDeclaration(Double.class, typeSolver),typeSolver);
@@ -207,7 +215,7 @@
     }
 
     @Test
-    public void testIsAssignableByGenerics() {
+    void testIsAssignableByGenerics() {
         assertEquals(false, listOfStrings.isAssignableBy(listOfWildcardExtendsString));
         assertEquals(false, listOfStrings.isAssignableBy(listOfWildcardExtendsString));
         assertEquals(true, listOfWildcardExtendsString.isAssignableBy(listOfStrings));
@@ -217,7 +225,7 @@
     }
 
     @Test
-    public void testIsAssignableByGenericsInheritance() {
+    void testIsAssignableByGenericsInheritance() {
         assertEquals(true, collectionOfString.isAssignableBy(collectionOfString));
         assertEquals(true, collectionOfString.isAssignableBy(listOfStrings));
         assertEquals(true, collectionOfString.isAssignableBy(linkedListOfString));
@@ -232,7 +240,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsConsideringTypeParameters() {
+    void testGetAllAncestorsConsideringTypeParameters() {
         assertTrue(linkedListOfString.getAllAncestors().contains(object));
         assertTrue(linkedListOfString.getAllAncestors().contains(listOfStrings));
         assertTrue(linkedListOfString.getAllAncestors().contains(collectionOfString));
@@ -256,7 +264,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsConsideringGenericsCases() {
+    void testGetAllAncestorsConsideringGenericsCases() {
         ReferenceTypeImpl foo = new ReferenceTypeImpl(new ReflectionClassDeclaration(Foo.class, typeSolver), typeSolver);
         ReferenceTypeImpl bar = new ReferenceTypeImpl(new ReflectionClassDeclaration(Bar.class, typeSolver), typeSolver);
         ReferenceTypeImpl left, right;
@@ -386,7 +394,7 @@
     }
 
     @Test
-    public void charSequenceIsAssignableToObject() {
+    void charSequenceIsAssignableToObject() {
         TypeSolver typeSolver = new ReflectionTypeSolver();
         ReferenceTypeImpl charSequence = new ReferenceTypeImpl(new ReflectionInterfaceDeclaration(CharSequence.class, typeSolver), typeSolver);
         ReferenceTypeImpl object = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
@@ -395,7 +403,7 @@
     }
 
     @Test
-    public void testGetFieldTypeExisting() {
+    void testGetFieldTypeExisting() {
         class Foo<A> {
             List<A> elements;
         }
@@ -423,7 +431,7 @@
     }
 
     @Test
-    public void testGetFieldTypeUnexisting() {
+    void testGetFieldTypeUnexisting() {
         class Foo<A> {
             List<A> elements;
         }
@@ -441,7 +449,7 @@
     }
 
     @Test
-    public void testTypeParamValue() {
+    void testTypeParamValue() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         ResolvedClassDeclaration abstractList = new ReflectionClassDeclaration(AbstractList.class, typeResolver);
@@ -460,7 +468,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsOnRawType() {
+    void testGetAllAncestorsOnRawType() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         ResolvedReferenceType rawArrayList = new ReferenceTypeImpl(arraylist, typeResolver);
@@ -482,7 +490,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForInterface() {
+    void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForInterface() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedInterfaceDeclaration list = new ReflectionInterfaceDeclaration(List.class, typeResolver);
         ResolvedType string = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeResolver), typeResolver);
@@ -498,7 +506,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForClassAbstractCollection() {
+    void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForClassAbstractCollection() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration abstractCollection = new ReflectionClassDeclaration(AbstractCollection.class, typeResolver);
         ResolvedType string = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeResolver), typeResolver);
@@ -514,7 +522,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForClassAbstractList() {
+    void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForClassAbstractList() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration abstractList = new ReflectionClassDeclaration(AbstractList.class, typeResolver);
         ResolvedType string = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeResolver), typeResolver);
@@ -532,7 +540,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForClassArrayList() {
+    void testGetAllAncestorsOnTypeWithSpecifiedTypeParametersForClassArrayList() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         ResolvedType string = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeResolver), typeResolver);
@@ -554,7 +562,7 @@
     }
 
     @Test
-    public void testTypeParametersValues() {
+    void testTypeParametersValues() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedReferenceType stream = new ReferenceTypeImpl(new ReflectionInterfaceDeclaration(Stream.class, typeResolver), typeResolver);
         assertEquals(1, stream.typeParametersValues().size());
@@ -562,7 +570,7 @@
     }
 
     @Test
-    public void testReplaceTypeVariables() {
+    void testReplaceTypeVariables() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedInterfaceDeclaration streamInterface = new ReflectionInterfaceDeclaration(Stream.class, typeResolver);
         ResolvedReferenceType stream = new ReferenceTypeImpl(streamInterface, typeResolver);
@@ -580,7 +588,7 @@
     }
 
     @Test
-    public void testReplaceTypeVariablesWithLambdaInBetween() {
+    void testReplaceTypeVariablesWithLambdaInBetween() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedInterfaceDeclaration streamInterface = new ReflectionInterfaceDeclaration(Stream.class, typeResolver);
         ResolvedReferenceType stream = new ReferenceTypeImpl(streamInterface, typeResolver);
@@ -597,4 +605,118 @@
         assertEquals("java.util.stream.Stream<java.lang.String>", streamReplaced.describe());
     }
 
+    @Test
+    void testDirectAncestorsOfObject() {
+        assertEquals(0, object.getDirectAncestors().size());
+    }
+
+    @Test
+    void testDirectAncestorsOfInterface() {
+        ResolvedReferenceType iterableOfString = new ReferenceTypeImpl(
+                new ReflectionInterfaceDeclaration(Iterable.class, typeSolver),
+                ImmutableList.of(new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver)), typeSolver);
+        assertEquals(1, iterableOfString.getDirectAncestors().size());
+        ResolvedReferenceType ancestor = iterableOfString.getDirectAncestors().get(0);
+        assertEquals("java.lang.Object", ancestor.getQualifiedName());
+        assertEquals(true, ancestor.getTypeParametersMap().isEmpty());
+    }
+
+    @Test
+    void testDirectAncestorsOfInterfaceExtendingInterface() {
+        assertEquals(2, collectionOfString.getDirectAncestors().size());
+        ResolvedReferenceType ancestor1 = collectionOfString.getDirectAncestors().get(0);
+        assertEquals("java.lang.Iterable", ancestor1.getQualifiedName());
+        assertEquals(1, ancestor1.getTypeParametersMap().size());
+        assertEquals("T", ancestor1.getTypeParametersMap().get(0).a.getName());
+        assertEquals("java.lang.String", ancestor1.getTypeParametersMap().get(0).b.describe());
+        ResolvedReferenceType ancestor2 = collectionOfString.getDirectAncestors().get(1);
+        assertEquals("java.lang.Object", ancestor2.getQualifiedName());
+        assertEquals(true, ancestor2.getTypeParametersMap().isEmpty());
+    }
+
+    @Test
+    void testDirectAncestorsOfClassWithoutSuperClassOrInterfaces() {
+        ResolvedReferenceType buffer = new ReferenceTypeImpl(
+                new ReflectionClassDeclaration(Buffer.class, typeSolver), typeSolver);
+        Set<String> ancestors = buffer.getDirectAncestors().stream().map(a -> a.describe()).collect(Collectors.toSet());
+        assertEquals(new HashSet<>(Arrays.asList("java.lang.Object")), ancestors);
+    }
+
+    @Test
+    void testDirectAncestorsOfObjectClass() {
+        ResolvedReferenceType object = new ReferenceTypeImpl(
+                new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
+        Set<String> ancestors = object.getDirectAncestors().stream().map(a -> a.describe()).collect(Collectors.toSet());
+        assertEquals(new HashSet<>(), ancestors);
+    }
+
+    @Test
+    void testDirectAncestorsOfClassWithSuperClass() {
+        ResolvedReferenceType charbuffer = new ReferenceTypeImpl(
+                new ReflectionClassDeclaration(CharBuffer.class, typeSolver), typeSolver);
+        Set<String> ancestors = charbuffer.getDirectAncestors().stream().map(a -> a.describe()).collect(Collectors.toSet());
+        assertEquals(new HashSet<>(Arrays.asList("java.lang.CharSequence", "java.lang.Appendable",
+                "java.nio.Buffer", "java.lang.Readable", "java.lang.Comparable<java.nio.CharBuffer>")), ancestors);
+    }
+
+    @Test
+    void testDirectAncestorsOfClassWithInterfaces() {
+        Set<String> ancestors = string.getDirectAncestors().stream().map(a -> a.describe()).collect(Collectors.toSet());
+        assertEquals(new HashSet<>(Arrays.asList("java.lang.CharSequence",
+                "java.lang.Object",
+                "java.lang.Comparable<java.lang.String>",
+                "java.io.Serializable")), ancestors);
+    }
+
+    @Test
+    void testDeclaredFields() {
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        String code = "class A { private int i; char c; public long l; } class B extends A { private float f; boolean b; };";
+        ParserConfiguration parserConfiguration = new ParserConfiguration();
+        parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver));
+
+        CompilationUnit cu = new JavaParser(parserConfiguration)
+                .parse(ParseStart.COMPILATION_UNIT, new StringProvider(code)).getResult().get();
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        ClassOrInterfaceDeclaration classB = cu.getClassByName("B").get();
+
+        ResolvedReferenceType rtA = new ReferenceTypeImpl(classA.resolve(), typeSolver);
+        ResolvedReferenceType rtB = new ReferenceTypeImpl(classB.resolve(), typeSolver);
+
+        assertEquals(3, rtA.getDeclaredFields().size());
+        assertTrue(rtA.getDeclaredFields().stream().anyMatch(f -> f.getName().equals("i")));
+        assertTrue(rtA.getDeclaredFields().stream().anyMatch(f -> f.getName().equals("c")));
+        assertTrue(rtA.getDeclaredFields().stream().anyMatch(f -> f.getName().equals("l")));
+
+        assertEquals(2, rtB.getDeclaredFields().size());
+        assertTrue(rtB.getDeclaredFields().stream().anyMatch(f -> f.getName().equals("f")));
+        assertTrue(rtB.getDeclaredFields().stream().anyMatch(f -> f.getName().equals("b")));
+    }
+
+    @Test
+    void testGetAllFieldsVisibleToInheritors() {
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        String code = "class A { private int i; char c; public long l; } class B extends A { private float f; boolean b; };";
+        ParserConfiguration parserConfiguration = new ParserConfiguration();
+        parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver));
+
+        CompilationUnit cu = new JavaParser(parserConfiguration)
+                .parse(ParseStart.COMPILATION_UNIT, new StringProvider(code)).getResult().get();
+
+        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
+        ClassOrInterfaceDeclaration classB = cu.getClassByName("B").get();
+
+        ResolvedReferenceType rtA = new ReferenceTypeImpl(classA.resolve(), typeSolver);
+        ResolvedReferenceType rtB = new ReferenceTypeImpl(classB.resolve(), typeSolver);
+
+        assertEquals(2, rtA.getAllFieldsVisibleToInheritors().size());
+        assertTrue(rtA.getAllFieldsVisibleToInheritors().stream().anyMatch(f -> f.getName().equals("c")));
+        assertTrue(rtA.getAllFieldsVisibleToInheritors().stream().anyMatch(f -> f.getName().equals("l")));
+
+        assertEquals(3, rtB.getAllFieldsVisibleToInheritors().size());
+        assertTrue(rtB.getAllFieldsVisibleToInheritors().stream().anyMatch(f -> f.getName().equals("c")));
+        assertTrue(rtB.getAllFieldsVisibleToInheritors().stream().anyMatch(f -> f.getName().equals("l")));
+        assertTrue(rtB.getAllFieldsVisibleToInheritors().stream().anyMatch(f -> f.getName().equals("b")));
+    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/TypeVariableUsageTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/TypeVariableUsageTest.java
index 1808b9c..fdf4290 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/TypeVariableUsageTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/TypeVariableUsageTest.java
@@ -21,21 +21,21 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.*;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class TypeVariableUsageTest {
+class TypeVariableUsageTest {
 
     private ResolvedTypeVariable tpA;
     private ReferenceTypeImpl tpString;
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         tpA = new ResolvedTypeVariable(ResolvedTypeParameterDeclaration.onType("A", "foo.Bar", Collections.emptyList()));
         
         typeSolver = new ReflectionTypeSolver();
@@ -43,7 +43,7 @@
     }
 
     @Test
-    public void testIsAssignableBySimple() {
+    void testIsAssignableBySimple() {
         assertEquals(false, tpString.isAssignableBy(tpA));
     }
 
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/VoidTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/VoidTypeTest.java
index 2c88ebb..d439750 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/VoidTypeTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/VoidTypeTest.java
@@ -26,15 +26,16 @@
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
 import java.util.List;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class VoidTypeTest {
+class VoidTypeTest {
 
     private ResolvedArrayType arrayOfBooleans;
     private ResolvedArrayType arrayOfListOfA;
@@ -42,8 +43,8 @@
     private ReferenceTypeImpl STRING;
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
         OBJECT = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
         STRING = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
@@ -54,62 +55,62 @@
     }
 
     @Test
-    public void testIsArray() {
+    void testIsArray() {
         assertEquals(false, ResolvedVoidType.INSTANCE.isArray());
     }
 
     @Test
-    public void testIsPrimitive() {
+    void testIsPrimitive() {
         assertEquals(false, ResolvedVoidType.INSTANCE.isPrimitive());
     }
 
     @Test
-    public void testIsNull() {
+    void testIsNull() {
         assertEquals(false, ResolvedVoidType.INSTANCE.isNull());
     }
 
     @Test
-    public void testIsReference() {
+    void testIsReference() {
         assertEquals(false, ResolvedVoidType.INSTANCE.isReference());
     }
 
     @Test
-    public void testIsReferenceType() {
+    void testIsReferenceType() {
         assertEquals(false, ResolvedVoidType.INSTANCE.isReferenceType());
     }
 
     @Test
-    public void testIsVoid() {
+    void testIsVoid() {
         assertEquals(true, ResolvedVoidType.INSTANCE.isVoid());
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         assertEquals(false, ResolvedVoidType.INSTANCE.isTypeVariable());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsReferenceTypeUsage() {
-        ResolvedVoidType.INSTANCE.asReferenceType();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsTypeParameter() {
-        ResolvedVoidType.INSTANCE.asTypeParameter();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsArrayTypeUsage() {
-        ResolvedVoidType.INSTANCE.asArrayType();
+    @Test
+    void testAsReferenceTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> ResolvedVoidType.INSTANCE.asReferenceType());
     }
 
     @Test
-    public void testAsDescribe() {
+    void testAsTypeParameter() {
+        assertThrows(UnsupportedOperationException.class, () -> ResolvedVoidType.INSTANCE.asTypeParameter());
+    }
+
+    @Test
+    void testAsArrayTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> ResolvedVoidType.INSTANCE.asArrayType());
+    }
+
+    @Test
+    void testAsDescribe() {
         assertEquals("void", ResolvedVoidType.INSTANCE.describe());
     }
 
     @Test
-    public void testIsAssignableBy() {
+    void testIsAssignableBy() {
         try {
             assertEquals(false, ResolvedVoidType.INSTANCE.isAssignableBy(NullType.INSTANCE));
             fail();
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/WildcardUsageTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/WildcardUsageTest.java
index 705805d..c590be5 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/WildcardUsageTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/model/typesystem/WildcardUsageTest.java
@@ -22,15 +22,16 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class WildcardUsageTest {
+class WildcardUsageTest {
 
     class Foo {
     }
@@ -54,8 +55,8 @@
     private ResolvedWildcard extendsString;
     private ResolvedTypeVariable a;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
         foo = new ReferenceTypeImpl(new ReflectionClassDeclaration(Foo.class, typeSolver), typeSolver);
         bar = new ReferenceTypeImpl(new ReflectionClassDeclaration(Bar.class, typeSolver), typeSolver);
@@ -73,7 +74,7 @@
     }
 
     @Test
-    public void testIsArray() {
+    void testIsArray() {
         assertEquals(false, unbounded.isArray());
         assertEquals(false, superFoo.isArray());
         assertEquals(false, superBar.isArray());
@@ -82,7 +83,7 @@
     }
 
     @Test
-    public void testIsPrimitive() {
+    void testIsPrimitive() {
         assertEquals(false, unbounded.isPrimitive());
         assertEquals(false, superFoo.isPrimitive());
         assertEquals(false, superBar.isPrimitive());
@@ -91,7 +92,7 @@
     }
 
     @Test
-    public void testIsNull() {
+    void testIsNull() {
         assertEquals(false, unbounded.isNull());
         assertEquals(false, superFoo.isNull());
         assertEquals(false, superBar.isNull());
@@ -100,7 +101,7 @@
     }
 
     @Test
-    public void testIsReference() {
+    void testIsReference() {
         assertEquals(true, unbounded.isReference());
         assertEquals(true, superFoo.isReference());
         assertEquals(true, superBar.isReference());
@@ -109,7 +110,7 @@
     }
 
     @Test
-    public void testIsReferenceType() {
+    void testIsReferenceType() {
         assertEquals(false, unbounded.isReferenceType());
         assertEquals(false, superFoo.isReferenceType());
         assertEquals(false, superBar.isReferenceType());
@@ -118,7 +119,7 @@
     }
 
     @Test
-    public void testIsVoid() {
+    void testIsVoid() {
         assertEquals(false, unbounded.isVoid());
         assertEquals(false, superFoo.isVoid());
         assertEquals(false, superBar.isVoid());
@@ -127,7 +128,7 @@
     }
 
     @Test
-    public void testIsTypeVariable() {
+    void testIsTypeVariable() {
         assertEquals(false, unbounded.isTypeVariable());
         assertEquals(false, superFoo.isTypeVariable());
         assertEquals(false, superBar.isTypeVariable());
@@ -136,7 +137,7 @@
     }
 
     @Test
-    public void testIsWildcard() {
+    void testIsWildcard() {
         assertEquals(true, unbounded.isWildcard());
         assertEquals(true, superFoo.isWildcard());
         assertEquals(true, superBar.isWildcard());
@@ -144,28 +145,28 @@
         assertEquals(true, extendsBar.isWildcard());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsArrayTypeUsage() {
-        unbounded.asArrayType();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsReferenceTypeUsage() {
-        unbounded.asReferenceType();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsTypeParameter() {
-        unbounded.asTypeParameter();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsPrimitive() {
-        unbounded.asPrimitive();
+    @Test
+    void testAsArrayTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> unbounded.asArrayType());
     }
 
     @Test
-    public void testAsWildcard() {
+    void testAsReferenceTypeUsage() {
+        assertThrows(UnsupportedOperationException.class, () -> unbounded.asReferenceType());
+    }
+
+    @Test
+    void testAsTypeParameter() {
+        assertThrows(UnsupportedOperationException.class, () -> unbounded.asTypeParameter());
+    }
+
+    @Test
+    void testAsPrimitive() {
+        assertThrows(UnsupportedOperationException.class, () -> unbounded.asPrimitive());
+    }
+
+    @Test
+    void testAsWildcard() {
         assertTrue(unbounded == unbounded.asWildcard());
         assertTrue(superFoo == superFoo.asWildcard());
         assertTrue(superBar == superBar.asWildcard());
@@ -174,7 +175,7 @@
     }
 
     @Test
-    public void testAsDescribe() {
+    void testAsDescribe() {
         assertEquals("?", unbounded.describe());
         assertEquals("? super com.github.javaparser.symbolsolver.model.typesystem.WildcardUsageTest.Foo", superFoo.describe());
         assertEquals("? super com.github.javaparser.symbolsolver.model.typesystem.WildcardUsageTest.Bar", superBar.describe());
@@ -183,7 +184,7 @@
     }
 
     @Test
-    public void testReplaceParam() {
+    void testReplaceParam() {
         ResolvedTypeParameterDeclaration tpA = ResolvedTypeParameterDeclaration.onType("A", "foo.Bar", Collections.emptyList());
         ResolvedTypeParameterDeclaration tpB = ResolvedTypeParameterDeclaration.onType("B", "foo.Bar", Collections.emptyList());
         assertTrue(unbounded == unbounded.replaceTypeVariables(tpA, string));
@@ -196,7 +197,7 @@
     }
 
     @Test
-    public void testIsAssignableBySimple() {
+    void testIsAssignableBySimple() {
         assertEquals(false, unbounded.isAssignableBy(object));
         assertEquals(true, object.isAssignableBy(unbounded));
         assertEquals(false, string.isAssignableBy(unbounded));
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclarationTest.java
index 8de0e23..7a45ec9 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclarationTest.java
@@ -17,30 +17,31 @@
 package com.github.javaparser.symbolsolver.reflectionmodel;
 
 import com.github.javaparser.ast.AccessSpecifier;
+import com.github.javaparser.ast.Modifier;
 import com.github.javaparser.resolution.declarations.*;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedTypeVariable;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.io.Serializable;
 import java.util.*;
 import java.util.stream.Collectors;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static java.util.Comparator.*;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class ReflectionClassDeclarationTest extends AbstractTest {
-    
+class ReflectionClassDeclarationTest extends AbstractSymbolResolutionTest {
+
     private TypeSolver typeResolver = new ReflectionTypeSolver(false);
 
     @Test
-    public void testIsClass() {
+    void testIsClass() {
         class Foo<E> {
             E field;
         }
@@ -57,7 +58,7 @@
     }
 
     @Test
-    public void testGetSuperclassSimpleImplicit() {
+    void testGetSuperclassSimpleImplicit() {
         class Foo<E> {
             E field;
         }
@@ -71,7 +72,7 @@
     }
 
     @Test
-    public void testGetSuperclassSimple() {
+    void testGetSuperclassSimple() {
         class Bar {
         }
         class Foo<E> extends Bar {
@@ -87,7 +88,7 @@
     }
 
     @Test
-    public void testGetSuperclassWithGenericSimple() {
+    void testGetSuperclassWithGenericSimple() {
         class Foo<E> {
             E field;
         }
@@ -105,7 +106,7 @@
     }
 
     @Test
-    public void testGetSuperclassWithGenericInheritanceSameName() {
+    void testGetSuperclassWithGenericInheritanceSameName() {
         class Foo<E> {
             E field;
         }
@@ -127,7 +128,7 @@
     }
 
     @Test
-    public void testGetSuperclassWithGenericInheritanceDifferentName() {
+    void testGetSuperclassWithGenericInheritanceDifferentName() {
         class Foo<E> {
             E field;
         }
@@ -144,7 +145,7 @@
     }
 
     @Test
-    public void testGetFieldDeclarationTypeVariableInheritance() {
+    void testGetFieldDeclarationTypeVariableInheritance() {
         class Foo<E> {
             E field;
         }
@@ -166,37 +167,48 @@
     }
 
     @Test
-    public void testGetDeclaredMethods() {
+    void testGetDeclaredMethods() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedReferenceTypeDeclaration string = new ReflectionClassDeclaration(String.class, typeResolver);
         List<ResolvedMethodDeclaration> methods = string.getDeclaredMethods().stream()
-                .filter(m -> m.accessSpecifier() != AccessSpecifier.PRIVATE && m.accessSpecifier() != AccessSpecifier.DEFAULT)
+                .filter(m -> m.accessSpecifier() != AccessSpecifier.PRIVATE && m.accessSpecifier() != AccessSpecifier.PACKAGE_PRIVATE)
                 .sorted((a, b) -> a.getName().compareTo(b.getName()))
                 .collect(Collectors.toList());
-        if (isJava9()) {
-            assertEquals(69, methods.size());
-        } else {
-            assertEquals(67, methods.size());
+        int foundCount = 0;
+        for (ResolvedMethodDeclaration method : methods) {
+            switch (method.getName()) {
+                case "charAt":
+                    assertFalse(method.isAbstract());
+                    assertEquals(1, method.getNumberOfParams());
+                    assertEquals("int", method.getParam(0).getType().describe());
+                    foundCount++;
+                    break;
+                case "compareTo":
+                    assertFalse(method.isAbstract());
+                    assertEquals(1, method.getNumberOfParams());
+                    assertEquals("java.lang.String", method.getParam(0).getType().describe());
+                    foundCount++;
+                    break;
+                case "concat":
+                    assertFalse(method.isAbstract());
+                    assertEquals(1, method.getNumberOfParams());
+                    assertEquals("java.lang.String", method.getParam(0).getType().describe());
+                    foundCount++;
+                    break;
+            }
         }
-        assertEquals("charAt", methods.get(0).getName());
-        assertEquals(false, methods.get(0).isAbstract());
-        assertEquals(1, methods.get(0).getNumberOfParams());
-        assertEquals("int", methods.get(0).getParam(0).getType().describe());
-        if (isJava9()) {
-            assertEquals("compareTo", methods.get(6).getName());
-            assertEquals(false, methods.get(6).isAbstract());
-            assertEquals(1, methods.get(6).getNumberOfParams());
-            assertEquals("java.lang.String", methods.get(6).getParam(0).getType().describe());
-        } else {
-            assertEquals("concat", methods.get(6).getName());
-            assertEquals(false, methods.get(6).isAbstract());
-            assertEquals(1, methods.get(6).getNumberOfParams());
-            assertEquals("java.lang.String", methods.get(6).getParam(0).getType().describe());
-        }
+        assertEquals(3, foundCount);
     }
 
     @Test
-    public void testGetInterfaces() {
+    void testGetConstructors() {
+        TypeSolver typeResolver = new ReflectionTypeSolver();
+        ResolvedReferenceTypeDeclaration locale = new ReflectionClassDeclaration(ClassWithSyntheticConstructor.class, typeResolver);
+        assertEquals(1, locale.getConstructors().size());
+    }
+
+    @Test
+    void testGetInterfaces() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         // Serializable, Cloneable, List<E>, RandomAccess
@@ -208,7 +220,7 @@
     }
 
     @Test
-    public void testGetAllInterfaces() {
+    void testGetAllInterfaces() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         // Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
@@ -222,7 +234,7 @@
     }
 
     @Test
-    public void testGetAllSuperclasses() {
+    void testGetAllSuperclasses() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         assertEquals(ImmutableSet.of(Object.class.getCanonicalName(),
@@ -235,7 +247,7 @@
     }
 
     @Test
-    public void testGetPackageName() {
+    void testGetPackageName() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         assertEquals("java.util", arraylist.getPackageName());
@@ -244,7 +256,7 @@
     }
 
     @Test
-    public void testGetClassName() {
+    void testGetClassName() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         assertEquals("ArrayList", arraylist.getClassName());
@@ -253,7 +265,7 @@
     }
 
     @Test
-    public void testGetQualifiedName() {
+    void testGetQualifiedName() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         assertEquals("java.util.ArrayList", arraylist.getQualifiedName());
@@ -271,7 +283,7 @@
     // getAllMethods
 
     @Test
-    public void testGetAllFields() {
+    void testGetAllFields() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         assertEquals(ImmutableSet.of("modCount", "serialVersionUID", "MAX_ARRAY_SIZE", "size", "elementData", "EMPTY_ELEMENTDATA", "DEFAULTCAPACITY_EMPTY_ELEMENTDATA", "DEFAULT_CAPACITY"),
@@ -283,7 +295,7 @@
     ///    
 
     @Test
-    public void testAllAncestors() {
+    void testAllAncestors() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedClassDeclaration arraylist = new ReflectionClassDeclaration(ArrayList.class, typeResolver);
         Map<String, ResolvedReferenceType> ancestors = new HashMap<>();
@@ -303,26 +315,26 @@
     }
 
     @Test
-    public void testGetSuperclassWithoutTypeParameters() {
+    void testGetSuperclassWithoutTypeParameters() {
         ReflectionClassDeclaration compilationUnit = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals("com.github.javaparser.ast.Node", compilationUnit.getSuperClass().getQualifiedName());
     }
 
     @Test
-    public void testGetSuperclassWithTypeParameters() {
+    void testGetSuperclassWithTypeParameters() {
         ReflectionClassDeclaration compilationUnit = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals("com.github.javaparser.ast.body.CallableDeclaration", compilationUnit.getSuperClass().getQualifiedName());
         assertEquals("com.github.javaparser.ast.body.ConstructorDeclaration", compilationUnit.getSuperClass().typeParametersMap().getValueBySignature("com.github.javaparser.ast.body.CallableDeclaration.T").get().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void testGetAllSuperclassesWithoutTypeParameters() {
+    void testGetAllSuperclassesWithoutTypeParameters() {
         ReflectionClassDeclaration cu = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("com.github.javaparser.ast.Node", "java.lang.Object"), cu.getAllSuperClasses().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
     }
 
     @Test
-    public void testGetAllSuperclassesWithTypeParameters() {
+    void testGetAllSuperclassesWithTypeParameters() {
         ReflectionClassDeclaration constructorDeclaration = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(4, constructorDeclaration.getAllSuperClasses().size());
         assertEquals(true, constructorDeclaration.getAllSuperClasses().stream().anyMatch(s -> s.getQualifiedName().equals("com.github.javaparser.ast.body.CallableDeclaration")));
@@ -348,7 +360,7 @@
     }
 
     @Test
-    public void testGetInterfacesWithoutParameters() {
+    void testGetInterfacesWithoutParameters() {
         ReflectionClassDeclaration compilationUnit = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of(), compilationUnit.getInterfaces().stream().map(i -> i.getQualifiedName()).collect(Collectors.toSet()));
 
@@ -365,7 +377,7 @@
     }
 
     @Test
-    public void testGetInterfacesWithParameters() {
+    void testGetInterfacesWithParameters() {
         ReflectionClassDeclaration constructorDeclaration = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         System.out.println(constructorDeclaration.getInterfaces().stream().map(t -> t.getQualifiedName()).collect(Collectors.toList()));
         assertEquals(8, constructorDeclaration.getInterfaces().size());
@@ -405,7 +417,7 @@
     }
 
     @Test
-    public void testGetAllInterfacesWithoutParameters() {
+    void testGetAllInterfacesWithoutParameters() {
         ReflectionClassDeclaration compilationUnit = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.visitor.Visitable", "com.github.javaparser.ast.observer.Observable",
                 "com.github.javaparser.HasParentNode", "com.github.javaparser.ast.nodeTypes.NodeWithRange",
@@ -440,7 +452,7 @@
     }
 
     @Test
-    public void testGetAllInterfacesWithParameters() {
+    void testGetAllInterfacesWithParameters() {
         ReflectionClassDeclaration constructorDeclaration = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         List<ResolvedReferenceType> interfaces = constructorDeclaration.getAllInterfaces();
         assertEquals(34, interfaces.size());
@@ -581,13 +593,13 @@
     }
 
     @Test
-    public void testGetAncestorsWithTypeParameters() {
+    void testGetAncestorsWithTypeParameters() {
         ReflectionClassDeclaration constructorDeclaration = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
         assertEquals(9, constructorDeclaration.getAncestors().size());
 
         ResolvedReferenceType ancestor;
         List<ResolvedReferenceType> ancestors = constructorDeclaration.getAncestors();
-        ancestors.sort(Comparator.comparing(ResolvedReferenceType::getQualifiedName));
+        ancestors.sort(comparing(ResolvedReferenceType::getQualifiedName));
 
         ancestor = ancestors.get(0);
         assertEquals("com.github.javaparser.ast.body.CallableDeclaration", ancestor.getQualifiedName());
@@ -626,7 +638,7 @@
     }
 
     @Test
-    public void testGetAllAncestorsWithoutTypeParameters() {
+    void testGetAllAncestorsWithoutTypeParameters() {
         ReflectionClassDeclaration cu = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.CompilationUnit");
         assertEquals(ImmutableSet.of("java.lang.Cloneable", "com.github.javaparser.ast.visitor.Visitable",
                 "com.github.javaparser.ast.observer.Observable", "com.github.javaparser.ast.Node",
@@ -635,12 +647,12 @@
     }
 
     @Test
-    public void testGetAllAncestorsWithTypeParameters() {
+    void testGetAllAncestorsWithTypeParameters() {
         ReflectionClassDeclaration constructorDeclaration = (ReflectionClassDeclaration) typeResolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         ResolvedReferenceType ancestor;
         List<ResolvedReferenceType> ancestors = constructorDeclaration.getAllAncestors();
-        ancestors.sort(Comparator.comparing(ResolvedReferenceType::getQualifiedName));
+        ancestors.sort(comparing(ResolvedReferenceType::getQualifiedName));
 
         ancestor = ancestors.remove(0);
         assertEquals("com.github.javaparser.HasParentNode", ancestor.getQualifiedName());
@@ -773,4 +785,20 @@
 
         assertTrue(ancestors.isEmpty());
     }
+
+    public static class ClassWithSyntheticConstructor {
+
+        private ClassWithSyntheticConstructor() {}
+
+        public static ClassWithSyntheticConstructor newInstance() {
+            return ClassWithSyntheticConstructorHelper.create();
+        }
+
+        private static class ClassWithSyntheticConstructorHelper {
+            public static ClassWithSyntheticConstructor create() {
+                return new ClassWithSyntheticConstructor();
+            }
+        }
+    }
+
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclarationTest.java
index 00379b0..4823317 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclarationTest.java
@@ -16,91 +16,110 @@
 
 package com.github.javaparser.symbolsolver.reflectionmodel;
 
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import java.util.Collections;
 
-public class ReflectionEnumDeclarationTest extends AbstractTest {
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+enum MyModifier {
+
+}
+
+class ReflectionEnumDeclarationTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver = new ReflectionTypeSolver(false);
 
+
+
     ///
     /// Test misc
     ///
 
     @Test
-    public void testIsClass() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    void testIsClass() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         assertEquals(false, modifier.isClass());
     }
 
     @Test
-    public void testIsInterface() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    void testIsInterface() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         assertEquals(false, modifier.isInterface());
     }
 
     @Test
-    public void testIsEnum() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    void testIsEnum() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         assertEquals(true, modifier.isEnum());
     }
 
     @Test
-    public void testIsTypeVariable() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    void testIsTypeVariable() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         assertEquals(false, modifier.isTypeParameter());
     }
 
     @Test
-    public void testIsType() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    void testIsType() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         assertEquals(true, modifier.isType());
     }
 
     @Test
-    public void testAsType() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    void testAsType() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         assertEquals(modifier, modifier.asType());
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsClass() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    @Test
+    void testAsClass() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         modifier.asClass();
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testAsInterface() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        modifier.asInterface();
-    }
+    });
+}
 
     @Test
-    public void testAsEnum() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
+    void testAsInterface() {
+        assertThrows(UnsupportedOperationException.class, () -> {
+            ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
+        modifier.asInterface();
+    });
+}
+
+    @Test
+    void testAsEnum() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
         assertEquals(modifier, modifier.asEnum());
     }
 
     @Test
-    public void testGetPackageName() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        assertEquals("com.github.javaparser.ast", modifier.getPackageName());
+    void testGetPackageName() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
+        assertEquals("com.github.javaparser.symbolsolver.reflectionmodel", modifier.getPackageName());
     }
 
     @Test
-    public void testGetClassName() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        assertEquals("Modifier", modifier.getClassName());
+    void testGetClassName() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
+        assertEquals("MyModifier", modifier.getClassName());
     }
 
     @Test
-    public void testGetQualifiedName() {
-        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.ast.Modifier");
-        assertEquals("com.github.javaparser.ast.Modifier", modifier.getQualifiedName());
+    void testGetQualifiedName() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
+        assertEquals("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier", modifier.getQualifiedName());
+    }
+
+    @Test
+    void testInternalTypesEmpty() {
+        ReflectionEnumDeclaration modifier = (ReflectionEnumDeclaration) typeSolver.solveType("com.github.javaparser.symbolsolver.reflectionmodel.MyModifier");
+        assertEquals(Collections.emptySet(), modifier.internalTypes());
     }
 
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclarationTest.java
index a526610..278c092 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclarationTest.java
@@ -16,60 +16,57 @@
 
 package com.github.javaparser.symbolsolver.reflectionmodel;
 
+import com.github.javaparser.resolution.declarations.ResolvedDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedInterfaceDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedReferenceType;
 import com.github.javaparser.resolution.types.ResolvedTypeVariable;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
-import static org.junit.Assert.assertEquals;
+import static java.util.Comparator.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class ReflectionInterfaceDeclarationTest extends AbstractTest {
+class ReflectionInterfaceDeclarationTest extends AbstractSymbolResolutionTest {
 
     @Test
-    public void testGetDeclaredMethods() {
+    void testGetDeclaredMethods() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedReferenceTypeDeclaration list = new ReflectionInterfaceDeclaration(List.class, typeResolver);
         List<ResolvedMethodDeclaration> methods = list.getDeclaredMethods().stream()
-                .sorted((a, b) -> a.getName().compareTo(b.getName()))
+                .sorted(comparing(ResolvedDeclaration::getName))
                 .collect(Collectors.toList());
-        if (isJava9()) {
-            assertEquals(40, methods.size());
-            assertEquals("clear", methods.get(4).getName());
-            assertEquals(true, methods.get(4).isAbstract());
-            assertEquals(0, methods.get(4).getNumberOfParams());
-            assertEquals("contains", methods.get(5).getName());
-            assertEquals(true, methods.get(5).isAbstract());
-            assertEquals(1, methods.get(5).getNumberOfParams());
-            assertEquals(true, methods.get(5).getParam(0).getType().isReferenceType());
-            assertEquals(Object.class.getCanonicalName(), methods.get(5).getParam(0).getType().asReferenceType().getQualifiedName());
-        } else {
-            assertEquals(28, methods.size());
-            assertEquals("clear", methods.get(4).getName());
-            assertEquals(true, methods.get(4).isAbstract());
-            assertEquals(0, methods.get(4).getNumberOfParams());
-            assertEquals("contains", methods.get(5).getName());
-            assertEquals(true, methods.get(5).isAbstract());
-            assertEquals(1, methods.get(5).getNumberOfParams());
-            assertEquals(true, methods.get(5).getParam(0).getType().isReferenceType());
-            assertEquals(Object.class.getCanonicalName(), methods.get(5).getParam(0).getType().asReferenceType().getQualifiedName());
+        int foundCount = 0;
+        for (ResolvedMethodDeclaration method : methods) {
+            switch (method.getName()) {
+                case "clear":
+                    assertTrue(method.isAbstract());
+                    assertEquals(0, method.getNumberOfParams());
+                    foundCount++;
+                    break;
+                case "contains":
+                    assertEquals(true, method.isAbstract());
+                    assertEquals(1, method.getNumberOfParams());
+                    assertEquals(true, method.getParam(0).getType().isReferenceType());
+                    assertEquals(Object.class.getCanonicalName(), method.getParam(0).getType().asReferenceType().getQualifiedName());
+                    foundCount++;
+                    break;
+            }
         }
+        assertEquals(2, foundCount);
     }
 
     @Test
-    public void testAllAncestors() {
+    void testAllAncestors() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
         ResolvedInterfaceDeclaration list = new ReflectionInterfaceDeclaration(List.class, typeResolver);
         Map<String, ResolvedReferenceType> ancestors = new HashMap<>();
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclarationTest.java
index 8a5be17..f0e5ca0 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclarationTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclarationTest.java
@@ -21,58 +21,47 @@
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.List;
-import java.util.Map;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class ReflectionMethodDeclarationTest {
+class ReflectionMethodDeclarationTest {
 
     @Test
-    public void testGetSignature() {
+    void testParameterNameOnClassesFromTheStdLibrary() {
         TypeSolver typeResolver = new ReflectionTypeSolver();
 
         ResolvedClassDeclaration object = new ReflectionClassDeclaration(Object.class, typeResolver);
         ResolvedInterfaceDeclaration list = new ReflectionInterfaceDeclaration(List.class, typeResolver);
 
-        ResolvedMethodDeclaration hashCode = object.getAllMethods().stream().filter(m -> m.getName().equals("hashCode")).findFirst().get().getDeclaration();
         ResolvedMethodDeclaration equals = object.getAllMethods().stream().filter(m -> m.getName().equals("equals")).findFirst().get().getDeclaration();
         ResolvedMethodDeclaration containsAll = list.getAllMethods().stream().filter(m -> m.getName().equals("containsAll")).findFirst().get().getDeclaration();
         ResolvedMethodDeclaration subList = list.getAllMethods().stream().filter(m -> m.getName().equals("subList")).findFirst().get().getDeclaration();
 
-        assertEquals("hashCode()", hashCode.getSignature());
-        assertEquals("equals(java.lang.Object)", equals.getSignature());
-        assertEquals("containsAll(java.util.Collection<? extends java.lang.Object>)", containsAll.getSignature());
-        assertEquals("subList(int, int)", subList.getSignature());
+        assertEquals("arg0", equals.getParam(0).getName());
+        assertEquals("arg0", containsAll.getParam(0).getName());
+        assertEquals("arg0", subList.getParam(0).getName());
+        assertEquals("arg1", subList.getParam(1).getName());
+    }
+
+    class Foo {
+        void myMethod(int a, char c) {
+
+        }
     }
 
     @Test
-    public void testGetGenericReturnType() {
-        TypeSolver typeResolver = new ReflectionTypeSolver();
+    void testParameterNameOnClassesFromThisProject() {
+        TypeSolver typeResolver = new ReflectionTypeSolver(false);
 
-        ResolvedInterfaceDeclaration map = new ReflectionInterfaceDeclaration(Map.class, typeResolver);
+        ResolvedClassDeclaration foo = new ReflectionClassDeclaration(Foo.class, typeResolver);
 
-        ResolvedMethodDeclaration put = map.getAllMethods().stream().filter(m -> m.getName().equals("put")).findFirst().get().getDeclaration();
-        assertEquals(true, put.getReturnType().isTypeVariable());
-        assertEquals(true, put.getReturnType().asTypeParameter().declaredOnType());
-        assertEquals("java.util.Map.V", put.getReturnType().asTypeParameter().getQualifiedName());
+        ResolvedMethodDeclaration myMethod = foo.getAllMethods().stream().filter(m -> m.getName().equals("myMethod")).findFirst().get().getDeclaration();
+
+        assertEquals("arg0", myMethod.getParam(0).getName());
+        assertEquals("arg1", myMethod.getParam(1).getName());
     }
 
-    @Test
-    public void testGetGenericParameters() {
-        TypeSolver typeResolver = new ReflectionTypeSolver();
-
-        ResolvedInterfaceDeclaration map = new ReflectionInterfaceDeclaration(Map.class, typeResolver);
-
-        ResolvedMethodDeclaration put = map.getAllMethods().stream().filter(m -> m.getName().equals("put")).findFirst().get().getDeclaration();
-        assertEquals(true, put.getParam(0).getType().isTypeVariable());
-        assertEquals(true, put.getParam(0).getType().asTypeParameter().declaredOnType());
-        assertEquals("java.util.Map.K", put.getParam(0).getType().asTypeParameter().getQualifiedName());
-
-        assertEquals(true, put.getParam(1).getType().isTypeVariable());
-        assertEquals(true, put.getParam(1).getType().asTypeParameter().declaredOnType());
-        assertEquals("java.util.Map.V", put.getParam(1).getType().asTypeParameter().getQualifiedName());
-    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclarationTest.java
new file mode 100644
index 0000000..d7cbe11
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclarationTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedInterfaceDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ReflectionParameterDeclarationTest {
+
+    @Test
+    void testGetSignature() {
+        TypeSolver typeResolver = new ReflectionTypeSolver();
+
+        ResolvedClassDeclaration object = new ReflectionClassDeclaration(Object.class, typeResolver);
+        ResolvedInterfaceDeclaration list = new ReflectionInterfaceDeclaration(List.class, typeResolver);
+
+        ResolvedMethodDeclaration hashCode = object.getAllMethods().stream().filter(m -> m.getName().equals("hashCode")).findFirst().get().getDeclaration();
+        ResolvedMethodDeclaration equals = object.getAllMethods().stream().filter(m -> m.getName().equals("equals")).findFirst().get().getDeclaration();
+        ResolvedMethodDeclaration containsAll = list.getAllMethods().stream().filter(m -> m.getName().equals("containsAll")).findFirst().get().getDeclaration();
+        ResolvedMethodDeclaration subList = list.getAllMethods().stream().filter(m -> m.getName().equals("subList")).findFirst().get().getDeclaration();
+
+        assertEquals("hashCode()", hashCode.getSignature());
+        assertEquals("equals(java.lang.Object)", equals.getSignature());
+        assertEquals("containsAll(java.util.Collection<? extends java.lang.Object>)", containsAll.getSignature());
+        assertEquals("subList(int, int)", subList.getSignature());
+    }
+
+    @Test
+    void testGetGenericReturnType() {
+        TypeSolver typeResolver = new ReflectionTypeSolver();
+
+        ResolvedInterfaceDeclaration map = new ReflectionInterfaceDeclaration(Map.class, typeResolver);
+
+        ResolvedMethodDeclaration put = map.getAllMethods().stream().filter(m -> m.getName().equals("put")).findFirst().get().getDeclaration();
+        assertEquals(true, put.getReturnType().isTypeVariable());
+        assertEquals(true, put.getReturnType().asTypeParameter().declaredOnType());
+        assertEquals("java.util.Map.V", put.getReturnType().asTypeParameter().getQualifiedName());
+    }
+
+    @Test
+    void testGetGenericParameters() {
+        TypeSolver typeResolver = new ReflectionTypeSolver();
+
+        ResolvedInterfaceDeclaration map = new ReflectionInterfaceDeclaration(Map.class, typeResolver);
+
+        ResolvedMethodDeclaration put = map.getAllMethods().stream().filter(m -> m.getName().equals("put")).findFirst().get().getDeclaration();
+        assertEquals(true, put.getParam(0).getType().isTypeVariable());
+        assertEquals(true, put.getParam(0).getType().asTypeParameter().declaredOnType());
+        assertEquals("java.util.Map.K", put.getParam(0).getType().asTypeParameter().getQualifiedName());
+
+        assertEquals(true, put.getParam(1).getType().isTypeVariable());
+        assertEquals(true, put.getParam(1).getType().asTypeParameter().declaredOnType());
+        assertEquals("java.util.Map.V", put.getParam(1).getType().asTypeParameter().getQualifiedName());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AbstractResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AbstractResolutionTest.java
index ded9267..d49cee0 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AbstractResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AbstractResolutionTest.java
@@ -16,17 +16,16 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseException;
+import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 
 import java.io.InputStream;
 
 /**
  * @author Federico Tomassetti
  */
-public abstract class AbstractResolutionTest extends AbstractTest {
+public abstract class AbstractResolutionTest extends AbstractSymbolResolutionTest {
 
     protected CompilationUnit parseSampleWithStandardExtension(String sampleName) {
         return parseSample(sampleName, "java");
@@ -41,6 +40,6 @@
         if (is == null) {
             throw new RuntimeException("Unable to find sample " + sampleName);
         }
-        return JavaParser.parse(is);
+        return StaticJavaParser.parse(is);
     }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaParserTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaParserTest.java
index 7b9f61b..3cf17fa 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaParserTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaParserTest.java
@@ -16,51 +16,49 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.SlowTest;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.SourceFileInfoExtractor;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
 
 import java.io.*;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-@Category(SlowTest.class)
-public class AnalyseJavaParserTest extends AbstractTest {
+@SlowTest
+class AnalyseJavaParserTest extends AbstractSymbolResolutionTest {
 
-    private static final File src = adaptPath(new File("src/test/test_sourcecode/javaparser_src/proper_source"));
+    private static final Path root = adaptPath("src/test/test_sourcecode/javaparser_src");
+    private static final Path properSrc = root.resolve("proper_source");
 
     private SourceFileInfoExtractor getSourceFileInfoExtractor() {
-        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
-        combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(src));
-        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_src/generated"))));
-        SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor();
-        sourceFileInfoExtractor.setTypeSolver(combinedTypeSolver);
+        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(
+                new ReflectionTypeSolver(),
+                new JavaParserTypeSolver(properSrc, new LeanParserConfiguration()),
+                new JavaParserTypeSolver(root.resolve("generated"), new LeanParserConfiguration()));
+        SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor(combinedTypeSolver);
         sourceFileInfoExtractor.setPrintFileName(false);
         return sourceFileInfoExtractor;
     }
 
-    static String readFile(File file)
+    private static String readFile(Path file)
             throws IOException {
-        byte[] encoded = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
+        byte[] encoded = Files.readAllBytes(file);
         return new String(encoded, StandardCharsets.UTF_8);
     }
 
     private static final boolean DEBUG = true;
 
-    private void parse(String fileName) throws IOException, ParseException {
-        File sourceFile = new File(src.getAbsolutePath() + "/" + fileName + ".java");
+    private void parse(String fileName) throws IOException {
+        Path sourceFile = properSrc.resolve( fileName + ".java");
         SourceFileInfoExtractor sourceFileInfoExtractor = getSourceFileInfoExtractor();
         OutputStream outErrStream = new ByteArrayOutputStream();
         PrintStream outErr = new PrintStream(outErrStream);
@@ -70,15 +68,15 @@
         sourceFileInfoExtractor.solve(sourceFile);
         String output = outErrStream.toString();
 
-        String path = "src/test/resources/javaparser_expected_output/" + fileName.replaceAll("/", "_") + ".txt";
-        File dstFile = adaptPath(new File(path));
+        String path = "expected_output/" + fileName.replaceAll("/", "_") + ".txt";
+        Path dstFile = adaptPath(root.resolve(path));
 
-        if (DEBUG && (sourceFileInfoExtractor.getKo() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)) {
+        if (DEBUG && (sourceFileInfoExtractor.getFailures() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)) {
             System.err.println(output);
         }
 
-        assertTrue("No failures expected when analyzing " + path, 0 == sourceFileInfoExtractor.getKo());
-        assertTrue("No UnsupportedOperationException expected when analyzing " + path, 0 == sourceFileInfoExtractor.getUnsupported());
+        assertEquals(0, sourceFileInfoExtractor.getFailures(), "No failures expected when analyzing " + path);
+        assertEquals(0, sourceFileInfoExtractor.getUnsupported(), "No UnsupportedOperationException expected when analyzing " + path);
 
         String expected = readFile(dstFile);
 
@@ -86,7 +84,7 @@
         String[] expectedLines = expected.split("\n");
 
         for (int i = 0; i < Math.min(outputLines.length, expectedLines.length); i++) {
-            assertEquals("Line " + (i + 1) + " of " + path + " is different from what is expected", expectedLines[i].trim(), outputLines[i].trim());
+            assertEquals(expectedLines[i].trim(), outputLines[i].trim(), "Line " + (i + 1) + " of " + path + " is different from what is expected");
         }
 
         assertEquals(expectedLines.length, outputLines.length);
@@ -100,27 +98,27 @@
     }
 
     @Test
-    public void parsePositionUtils() throws IOException, ParseException {
+    void parsePositionUtils() throws IOException {
         parse("com/github/javaparser/PositionUtils");
     }
 
     @Test
-    public void parseJavaParser() throws IOException, ParseException {
+    void parseJavaParser() throws IOException {
         parse("com/github/javaparser/JavaParser");
     }
 
     @Test
-    public void parseStatement() throws IOException, ParseException {
+    void parseStatement() throws IOException {
         parse("com/github/javaparser/ast/stmt/Statement");
     }
 
     @Test
-    public void parseCatchClause() throws IOException, ParseException {
+    void parseCatchClause() throws IOException {
         parse("com/github/javaparser/ast/stmt/CatchClause");
     }
 
     @Test
-    public void parseStatements() throws IOException, ParseException {
+    void parseStatements() throws IOException {
         parse("com/github/javaparser/ast/stmt/LabeledStmt");
         parse("com/github/javaparser/ast/stmt/BreakStmt");
         parse("com/github/javaparser/ast/stmt/ReturnStmt");
@@ -144,7 +142,7 @@
     }
 
     @Test
-    public void parseExpressions() throws IOException, ParseException {
+    void parseExpressions() throws IOException {
         parse("com/github/javaparser/ast/expr/NameExpr");
         parse("com/github/javaparser/ast/expr/FieldAccessExpr");
         parse("com/github/javaparser/ast/expr/CharLiteralExpr");
@@ -186,7 +184,7 @@
     }
 
     @Test
-    public void parseTypes() throws IOException, ParseException {
+    void parseTypes() throws IOException {
         parse("com/github/javaparser/ast/type/ClassOrInterfaceType");
         parse("com/github/javaparser/ast/type/PrimitiveType");
         parse("com/github/javaparser/ast/type/WildcardType");
@@ -197,7 +195,7 @@
     }
 
     @Test
-    public void parseVisitors() throws IOException, ParseException {
+    void parseVisitors() throws IOException {
         parse("com/github/javaparser/ast/visitor/EqualsVisitor");
         parse("com/github/javaparser/ast/visitor/ModifierVisitorAdapter");
         parse("com/github/javaparser/ast/visitor/DumpVisitor");
@@ -208,17 +206,17 @@
     }
 
     @Test
-    public void parseCloneVisitor() throws IOException, ParseException {
+    void parseCloneVisitor() throws IOException {
         parse("com/github/javaparser/ast/visitor/CloneVisitor");
     }
 
     @Test
-    public void parseSourcesHelper() throws IOException, ParseException {
+    void parseSourcesHelper() throws IOException {
         parse("com/github/javaparser/SourcesHelper");
     }
 
     @Test
-    public void parseComments() throws IOException, ParseException {
+    void parseComments() throws IOException {
         parse("com/github/javaparser/ast/comments/LineComment");
         parse("com/github/javaparser/ast/comments/Comment");
         parse("com/github/javaparser/ast/comments/CommentsParser");
@@ -228,7 +226,7 @@
     }
 
     @Test
-    public void parseTheRest() throws IOException, ParseException {
+    void parseTheRest() throws IOException {
         parse("com/github/javaparser/ast/internal/Utils");
         parse("com/github/javaparser/ast/body/AnnotationMemberDeclaration");
         parse("com/github/javaparser/ast/body/EnumDeclaration");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaSymbolSolver060Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaSymbolSolver060Test.java
index 1cce12a..78e6b15 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaSymbolSolver060Test.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseJavaSymbolSolver060Test.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.SlowTest;
 import com.github.javaparser.symbolsolver.SourceFileInfoExtractor;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
@@ -24,55 +23,52 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
+import org.junit.jupiter.api.Test;
 
 import java.io.*;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
 
 /**
  * We analyze JavaParser version 0.6.0.
  */
-@Category(SlowTest.class)
-public class AnalyseJavaSymbolSolver060Test extends AbstractResolutionTest {
+@SlowTest
+class AnalyseJavaSymbolSolver060Test extends AbstractResolutionTest {
 
-    private static final File root = adaptPath(new File("src/test/resources/javasymbolsolver_0_6_0"));
-    private static final File src = adaptPath(new File(root + "/src"));
-    private static final File lib = adaptPath(new File(root + "/lib"));
-    private static final File expectedOutput = adaptPath(new File(root + "/expected_output"));
+    private static final Path root = adaptPath("src/test/test_sourcecode/javasymbolsolver_0_6_0");
+    private static final Path src = root.resolve("src");
+    private static final Path lib = root.resolve("lib");
+    private static final Path expectedOutput = root.resolve("expected_output");
 
     private static SourceFileInfoExtractor getSourceFileInfoExtractor() {
-        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
-        combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(new File(src + "/java-symbol-solver-core")));
-        combinedTypeSolver.add(new JavaParserTypeSolver(new File(src + "/java-symbol-solver-logic")));
-        combinedTypeSolver.add(new JavaParserTypeSolver(new File(src + "/java-symbol-solver-model")));
         try {
-			combinedTypeSolver.add(new JarTypeSolver(lib + "/guava-21.0.jar"));
-			combinedTypeSolver.add(new JarTypeSolver(lib + "/javaparser-core-3.3.0.jar"));
-			combinedTypeSolver.add(new JarTypeSolver(lib + "/javaslang-2.0.3.jar"));
-			combinedTypeSolver.add(new JarTypeSolver(lib + "/javassist-3.19.0-GA.jar"));
-		} catch (IOException e) {
-			Assert.fail("one or more jar dependencies could not be found.");
-			e.printStackTrace();
-		}
-        SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor();
-        sourceFileInfoExtractor.setTypeSolver(combinedTypeSolver);
-        sourceFileInfoExtractor.setPrintFileName(false);
-        sourceFileInfoExtractor.setVerbose(true);
-        return sourceFileInfoExtractor;
+            CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(
+                    new ReflectionTypeSolver(),
+                    new JavaParserTypeSolver(new File(src + "/java-symbol-solver-core")),
+                    new JavaParserTypeSolver(new File(src + "/java-symbol-solver-logic")),
+                    new JavaParserTypeSolver(new File(src + "/java-symbol-solver-model")),
+                    new JarTypeSolver(lib + "/guava-21.0.jar"),
+                    new JarTypeSolver(lib + "/javaparser-core-3.3.0.jar"),
+                    new JarTypeSolver(lib + "/javaslang-2.0.3.jar"),
+                    new JarTypeSolver(lib + "/javassist-3.19.0-GA.jar"));
+            SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor(combinedTypeSolver);
+            sourceFileInfoExtractor.setPrintFileName(false);
+            sourceFileInfoExtractor.setVerbose(true);
+            return sourceFileInfoExtractor;
+        } catch (IOException e) {
+            fail("one or more jar dependencies could not be found.");
+            return null;
+        }
     }
 
     private static SourceFileInfoExtractor sourceFileInfoExtractor = getSourceFileInfoExtractor();
 
-    static String readFile(File file)
+    private static String readFile(File file)
             throws IOException {
         byte[] encoded = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
         return new String(encoded, StandardCharsets.UTF_8);
@@ -83,11 +79,9 @@
     /**
      * @param projectName is one of "java-symbol-solver-core", "java-symbol-solver-logic", "java-symbol-solver-model"
      * @param fileName describes the file being analyzed
-     * @throws IOException
-     * @throws ParseException
      */
-    private void parse(String projectName, String fileName) throws IOException, ParseException {
-        File sourceFile = new File(src.getAbsolutePath() + "/" + projectName + "/" + fileName + ".java");
+    private void parse(String projectName, String fileName) throws IOException {
+        Path sourceFile = src.resolve(projectName + "/" + fileName + ".java");
         OutputStream outErrStream = new ByteArrayOutputStream();
         PrintStream outErr = new PrintStream(outErrStream);
 
@@ -96,11 +90,11 @@
         sourceFileInfoExtractor.solveMethodCalls(sourceFile);
         String output = outErrStream.toString();
 
-        String path = adaptPath(expectedOutput).getPath() + "/" + projectName + "/" + fileName.replaceAll("/", "_") + ".txt";
-        File dstFile = new File(path);
+        String path = adaptPath(expectedOutput) + "/" + projectName + "/" + fileName.replaceAll("/", "_") + ".txt";
+        File dstFile = new File(path);  
 
-        if (isJava9()) {
-            String path9 = adaptPath(expectedOutput).getPath() + "/" + projectName + "/" + fileName.replaceAll("/", "_") + "_J9.txt";
+        if (isJavaVersion9OrAbove()) {
+            String path9 = adaptPath(expectedOutput) + "/" + projectName + "/" + fileName.replaceAll("/", "_") + "_J9.txt";
             File dstFile9 = new File(path9);
             if (dstFile9.exists()) {
                 path = path9;
@@ -108,19 +102,19 @@
             }
         }
 
-        if (DEBUG && (sourceFileInfoExtractor.getKo() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)) {
+        if (DEBUG && (sourceFileInfoExtractor.getFailures() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)) {
             System.err.println(output);
         }
 
-        assertTrue("No failures expected when analyzing " + path, 0 == sourceFileInfoExtractor.getKo());
-        assertTrue("No UnsupportedOperationException expected when analyzing " + path, 0 == sourceFileInfoExtractor.getUnsupported());
+        assertEquals(0, sourceFileInfoExtractor.getFailures(), "No failures expected when analyzing " + path);
+        assertEquals(0, sourceFileInfoExtractor.getUnsupported(), "No UnsupportedOperationException expected when analyzing " + path);
 
-        if (!dstFile.exists()) {
-            // If we need to update the file uncomment these lines
+        // If we need to update the file uncomment these lines
+//        if (!dstFile.exists()) {
 //            PrintWriter writer = new PrintWriter(dstFile.getAbsoluteFile(), "UTF-8");
 //            writer.print(output);
 //            writer.close();
-        }
+//        }
 
         String expected = readFile(dstFile);
 
@@ -128,7 +122,7 @@
         String[] expectedLines = expected.split("\n");
 
         for (int i = 0; i < Math.min(outputLines.length, expectedLines.length); i++) {
-            assertEquals("Line " + (i + 1) + " of " + path + " is different from what is expected", expectedLines[i].trim(), outputLines[i].trim());
+            assertEquals(expectedLines[i].trim(), outputLines[i].trim(), "Line " + (i + 1) + " of " + path + " is different from what is expected");
         }
 
         assertEquals(expectedLines.length, outputLines.length);
@@ -137,38 +131,42 @@
     }
 
     @Test
-    public void parseCoreSourceFileInfoExtractor() throws IOException, ParseException {
+    void parseCoreSourceFileInfoExtractor() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/SourceFileInfoExtractor");
     }
 
     @Test
-    public void parseCoreCoreResolution() throws IOException, ParseException {
+    void parseCoreCoreResolution() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/core/resolution/Context");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/core/resolution/ContextHelper");
     }
 
     @Test
-    public void parseCoreDeclarationsCommon() throws IOException, ParseException {
+    void parseCoreDeclarationsCommon() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic");
     }
 
     @Test
-    public void parseCoreJavaparserNavigator() throws IOException, ParseException {
+    void parseCoreJavaparserNavigator() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparser/Navigator");
     }
 
     @Test
-    public void parseCoreJavaparsermodel() throws IOException, ParseException {
+    void parseCoreJavaparsermodelTypeExtractor() throws IOException {
+        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor");
+    }
+
+    @Test
+    void parseCoreJavaparsermodel() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder");
-        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException");
     }
 
     @Test
-    public void parseCoreJavaparsermodelContexts() throws IOException, ParseException {
+    void parseCoreJavaparsermodelContexts() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext");
@@ -191,17 +189,33 @@
     }
 
     @Test
-    public void parseCoreJavaparsermodelDeclarations() throws IOException, ParseException {
-        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration");
-        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper");
-        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration");
+    void parseCoreJavaparsermodelJavaParserAnonymousClassDeclaration() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration");
+    }
+
+    @Test
+    void parseCoreJavaparsermodelJavaParserInterfaceDeclaration() throws IOException {
+        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration");
+    }
+
+    @Test
+    void parseCoreJavaparsermodelDeclarationsHelper() throws IOException {
+        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper");
+    }
+
+    @Test
+    void parseCoreJavaparsermodelDeclarationsJavaParserFieldDeclaration() throws IOException {
+        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration");
+    }
+
+    @Test
+    void parseCoreJavaparsermodelDeclarations() throws IOException {
+        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration");
+        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration");
-        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration");
-        parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration");
@@ -211,7 +225,7 @@
     }
 
     @Test
-    public void parseCoreJavaparsermodelDeclarators() throws IOException, ParseException {
+    void parseCoreJavaparsermodelDeclarators() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator");
@@ -220,8 +234,12 @@
     }
 
     @Test
-    public void parseCoreJavassistmodel() throws IOException, ParseException {
+    void parseCoreJavassistmodelJavassistClassDeclaration() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration");
+    }
+
+    @Test
+    void parseCoreJavassistmodel() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory");
@@ -235,13 +253,13 @@
     }
 
     @Test
-    public void parseCoreModelTypesystem() throws IOException, ParseException {
+    void parseCoreModelTypesystem() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/model/typesystem/LazyType");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl");
     }
 
     @Test
-    public void parseCoreReflectionmodel() throws IOException, ParseException {
+    void parseCoreReflectionmodel() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/MyObjectProvider");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration");
@@ -257,14 +275,14 @@
     }
 
     @Test
-    public void parseCoreReflectionmodelComparators() throws IOException, ParseException {
+    void parseCoreReflectionmodelComparators() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/ClassComparator");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/MethodComparator");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/ParameterComparator");
     }
 
     @Test
-    public void parseCoreResolution() throws IOException, ParseException {
+    void parseCoreResolution() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/ConstructorResolutionLogic");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/SymbolDeclarator");
@@ -272,7 +290,7 @@
     }
 
     @Test
-    public void parseCoreResolutionTypesolvers() throws IOException, ParseException {
+    void parseCoreResolutionTypesolvers() throws IOException {
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver");
         parse("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver");
@@ -281,18 +299,18 @@
     }
 
     @Test
-    public void parseLogic() throws IOException, ParseException {
-		parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration");
-		parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration");
-		parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ConfilictingGenericTypesException");
-		parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic");
-		parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceContext");
-		parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceVariableType");
-		parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ObjectProvider");
+    void parseLogic() throws IOException {
+        parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration");
+        parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration");
+        parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ConfilictingGenericTypesException");
+        parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic");
+        parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceContext");
+        parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceVariableType");
+        parse("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ObjectProvider");
     }
 
     @Test
-    public void parseModelDeclarations() throws IOException, ParseException {
+    void parseModelDeclarations() throws IOException {
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/AccessLevel");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/AnnotationDeclaration");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ClassDeclaration");
@@ -314,12 +332,12 @@
     }
 
     @Test
-    public void parseModelMethodsMethodUsage() throws IOException, ParseException {
+    void parseModelMethodsMethodUsage() throws IOException {
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/methods/MethodUsage");
     }
 
     @Test
-    public void parseModelResolution() throws IOException, ParseException {
+    void parseModelResolution() throws IOException {
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/SymbolReference");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/TypeSolver");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/UnsolvedSymbolException");
@@ -327,12 +345,16 @@
     }
 
     @Test
-    public void parseModelTypesystem() throws IOException, ParseException {
+    void parseModelTypesystemReferenceType() throws IOException {
+        parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/ReferenceType");
+    }
+
+    @Test
+    void parseModelTypesystem() throws IOException {
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/ArrayType");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/LambdaConstraintType");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/NullType");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/PrimitiveType");
-        parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/ReferenceType");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/Type");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/TypeTransformer");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/TypeVariable");
@@ -341,7 +363,7 @@
     }
 
     @Test
-    public void parseModelTypesystemParametrization() throws IOException, ParseException {
+    void parseModelTypesystemParametrization() throws IOException {
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametersMap");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParameterValueProvider");
         parse("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametrized");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserHelpersTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserHelpersTest.java
index 254609e..08c4cae 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserHelpersTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserHelpersTest.java
@@ -16,45 +16,44 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseException;
+import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.expr.NameExpr;
 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * We analize a more recent version of JavaParser, after the project moved to Java 8.
  */
-public class AnalyseNewJavaParserHelpersTest extends AbstractResolutionTest {
+class AnalyseNewJavaParserHelpersTest extends AbstractResolutionTest {
 
-    private static final File src = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
+    private static final Path src = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
 
     private static TypeSolver TYPESOLVER = typeSolver();
 
     private static TypeSolver typeSolver() {
         CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
         combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(src));
-        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
+        combinedTypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"), new LeanParserConfiguration()));
         return combinedTypeSolver;
     }
 
     private CompilationUnit parse(String fileName) throws IOException {
-        File sourceFile = new File(src.getAbsolutePath() + "/" + fileName + ".java");
-        return JavaParser.parse(sourceFile);
+        Path sourceFile = src.resolve(fileName + ".java");
+        return StaticJavaParser.parse(sourceFile);
     }
 
 //    @Test
@@ -80,7 +79,7 @@
 //    }
 
     @Test
-    public void nodesTypeIsCorrect() throws IOException {
+    void nodesTypeIsCorrect() throws IOException {
         CompilationUnit cu = parse("com/github/javaparser/utils/PositionUtils");
         NameExpr nodes = cu.findAll(NameExpr.class).stream().filter(it -> it.getName() != null && it.getName().getId().equals("nodes")).findFirst().get();
         ResolvedType type = JavaParserFacade.get(TYPESOLVER).solve(nodes).getCorrespondingDeclaration().getType();
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserTest.java
index 53c0e04..8cfedbd 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnalyseNewJavaParserTest.java
@@ -16,39 +16,37 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.SlowTest;
 import com.github.javaparser.symbolsolver.SourceFileInfoExtractor;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
 
 import java.io.*;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * We analyze a more recent version of JavaParser, after the project moved to Java 8.
  */
-@Category(SlowTest.class)
-public class AnalyseNewJavaParserTest extends AbstractResolutionTest {
+@SlowTest
+class AnalyseNewJavaParserTest extends AbstractResolutionTest {
 
-    private static final File src = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
+    private static final Path root = adaptPath("src/test/test_sourcecode/javaparser_new_src");
+    private static final Path src = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
 
     private static SourceFileInfoExtractor getSourceFileInfoExtractor() {
-        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
-        combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(src));
-        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
-        SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor();
-        sourceFileInfoExtractor.setTypeSolver(combinedTypeSolver);
+        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(
+                new ReflectionTypeSolver(),
+                new JavaParserTypeSolver(src, new LeanParserConfiguration()),
+                new JavaParserTypeSolver(root.resolve("javaparser-generated-sources"), new LeanParserConfiguration()));
+        SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor(combinedTypeSolver);
         sourceFileInfoExtractor.setPrintFileName(false);
         sourceFileInfoExtractor.setVerbose(true);
         return sourceFileInfoExtractor;
@@ -56,16 +54,16 @@
 
     private static SourceFileInfoExtractor sourceFileInfoExtractor = getSourceFileInfoExtractor();
 
-    static String readFile(File file)
+    static String readFile(Path file)
             throws IOException {
-        byte[] encoded = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
+        byte[] encoded = Files.readAllBytes(file);
         return new String(encoded, StandardCharsets.UTF_8);
     }
 
     private static final boolean DEBUG = true;
 
-    private void parse(String fileName) throws IOException, ParseException {
-        File sourceFile = new File(src.getAbsolutePath() + "/" + fileName + ".java");
+    private void parse(String fileName) throws IOException {
+        Path sourceFile = src.resolve(fileName + ".java");
         OutputStream outErrStream = new ByteArrayOutputStream();
         PrintStream outErr = new PrintStream(outErrStream);
 
@@ -74,29 +72,29 @@
         sourceFileInfoExtractor.solveMethodCalls(sourceFile);
         String output = outErrStream.toString();
 
-        File expectedOutput = new File("src/test/resources/javaparser_methodcalls_expected_output");
-        String path = adaptPath(expectedOutput).getPath() + "/" + fileName.replaceAll("/", "_") + ".txt";
-        File dstFile = new File(path);
+        Path expectedOutput = root.resolve("expected_output");
+        Path path = expectedOutput.resolve(fileName.replaceAll("/", "_") + ".txt");
+        Path dstFile = path;
 
-        if (isJava9()) {
-            String path9 = adaptPath(expectedOutput).getPath() + "/" + fileName.replaceAll("/", "_") + "_J9.txt";
-            File dstFile9 = new File(path9);
-            if (dstFile9.exists()) {
+        if (isJavaVersion9OrAbove()) {
+            Path path9 = expectedOutput.resolve(fileName.replaceAll("/", "_") + "_J9.txt");
+            Path dstFile9 = path9;
+            if (Files.exists(dstFile9)) {
                 path = path9;
                 dstFile = dstFile9;
             }
         }
 
-        if (DEBUG && (sourceFileInfoExtractor.getKo() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)) {
+        if (DEBUG && (sourceFileInfoExtractor.getFailures() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)) {
             System.err.println(output);
         }
 
-        assertTrue("No failures expected when analyzing " + path, 0 == sourceFileInfoExtractor.getKo());
-        assertTrue("No UnsupportedOperationException expected when analyzing " + path, 0 == sourceFileInfoExtractor.getUnsupported());
+        assertEquals(0, sourceFileInfoExtractor.getFailures(), "No failures expected when analyzing " + path);
+        assertEquals(0, sourceFileInfoExtractor.getUnsupported(), "No UnsupportedOperationException expected when analyzing " + path);
 
-        if (!dstFile.exists()) {
+        if (!Files.exists(dstFile)) {
             // If we need to update the file uncomment these lines
-            PrintWriter writer = new PrintWriter(dstFile.getAbsoluteFile(), "UTF-8");
+            PrintWriter writer = new PrintWriter(dstFile.toAbsolutePath().toFile(), "UTF-8");
             writer.print(output);
             writer.close();
         }
@@ -107,7 +105,7 @@
         String[] expectedLines = expected.split("\n");
 
         for (int i = 0; i < Math.min(outputLines.length, expectedLines.length); i++) {
-            assertEquals("Line " + (i + 1) + " of " + path + " is different from what is expected", expectedLines[i].trim(), outputLines[i].trim());
+            assertEquals(expectedLines[i].trim(), outputLines[i].trim(), "Line " + (i + 1) + " of " + path + " is different from what is expected");
         }
 
         assertEquals(expectedLines.length, outputLines.length);
@@ -116,32 +114,32 @@
     }
 
     @Test
-    public void parseUtilsUtils() throws IOException, ParseException {
+    void parseUtilsUtils() throws IOException {
         parse("com/github/javaparser/utils/Utils");
     }
 
     @Test
-    public void parseCommentsInserter() throws IOException, ParseException {
+    void parseCommentsInserter() throws IOException {
         parse("com/github/javaparser/CommentsInserter");
     }
 
     @Test
-    public void parsePositionUtils() throws IOException, ParseException {
+    void parsePositionUtils() throws IOException {
         parse("com/github/javaparser/utils/PositionUtils");
     }
 
     @Test
-    public void parseModifier() throws IOException, ParseException {
+    void parseModifier() throws IOException {
         parse("com/github/javaparser/ast/Modifier");
     }
 
     @Test
-    public void parseNodeWithMembers() throws IOException, ParseException {
+    void parseNodeWithMembers() throws IOException {
         parse("com/github/javaparser/ast/nodeTypes/NodeWithMembers");
     }
 
     @Test
-    public void parseAstStmts() throws IOException, ParseException {
+    void parseAstStmts() throws IOException {
         parse("com/github/javaparser/ast/stmt/AssertStmt");
         parse("com/github/javaparser/ast/stmt/BlockStmt");
         parse("com/github/javaparser/ast/stmt/BreakStmt");
@@ -167,7 +165,7 @@
     }
 
     @Test
-    public void parseAstExprs() throws IOException, ParseException {
+    void parseAstExprs() throws IOException {
         parse("com/github/javaparser/ast/expr/AnnotationExpr");
         parse("com/github/javaparser/ast/expr/ArrayAccessExpr");
         parse("com/github/javaparser/ast/expr/ArrayCreationExpr");
@@ -208,12 +206,12 @@
     }
 
     @Test
-    public void parseVariableDeclarationExpr() throws IOException, ParseException {
+    void parseVariableDeclarationExpr() throws IOException {
         parse("com/github/javaparser/ast/expr/VariableDeclarationExpr");
     }
 
     @Test
-    public void parseAstBody() throws IOException, ParseException {
+    void parseAstBody() throws IOException {
         parse("com/github/javaparser/ast/body/AnnotationDeclaration");
         parse("com/github/javaparser/ast/body/AnnotationMemberDeclaration");
         parse("com/github/javaparser/ast/body/BodyDeclaration");
@@ -233,7 +231,7 @@
     }
 
     @Test
-    public void parseAstComments() throws IOException, ParseException {
+    void parseAstComments() throws IOException {
         parse("com/github/javaparser/ast/comments/BlockComment");
         parse("com/github/javaparser/ast/comments/Comment");
         parse("com/github/javaparser/ast/comments/CommentsCollection");
@@ -242,11 +240,15 @@
     }
 
     @Test
-    public void parseAstRest() throws IOException, ParseException {
+    void parseAstCompilationUnit() throws IOException {
+        parse("com/github/javaparser/ast/CompilationUnit");
+    }
+
+    @Test
+    void parseAstRest() throws IOException {
         parse("com/github/javaparser/ast/AccessSpecifier");
         parse("com/github/javaparser/ast/ArrayBracketPair");
         parse("com/github/javaparser/ast/ArrayCreationLevel");
-        parse("com/github/javaparser/ast/CompilationUnit");
         parse("com/github/javaparser/ast/Example");
         parse("com/github/javaparser/ast/ImportDeclaration");
         parse("com/github/javaparser/ast/Node");
@@ -255,7 +257,7 @@
     }
 
     @Test
-    public void parseAstNodeTypes() throws IOException, ParseException {
+    void parseAstNodeTypes() throws IOException {
         parse("com/github/javaparser/ast/nodeTypes/NodeWithAnnotations");
         parse("com/github/javaparser/ast/nodeTypes/NodeWithBlockStmt");
         parse("com/github/javaparser/ast/nodeTypes/NodeWithBody");
@@ -275,7 +277,7 @@
     }
 
     @Test
-    public void parseAstTypes() throws IOException, ParseException {
+    void parseAstTypes() throws IOException {
         parse("com/github/javaparser/ast/type/ArrayType");
         parse("com/github/javaparser/ast/type/ClassOrInterfaceType");
         parse("com/github/javaparser/ast/type/IntersectionType");
@@ -290,7 +292,7 @@
     }
 
     @Test
-    public void parseAstVisitor() throws IOException, ParseException {
+    void parseAstVisitor() throws IOException {
         parse("com/github/javaparser/ast/visitor/CloneVisitor");
         parse("com/github/javaparser/ast/visitor/EqualsVisitor");
         parse("com/github/javaparser/ast/visitor/GenericVisitor");
@@ -302,18 +304,18 @@
     }
 
     @Test
-    public void parseDumpVisitor() throws IOException, ParseException {
+    void parseDumpVisitor() throws IOException {
         parse("com/github/javaparser/ast/visitor/DumpVisitor");
     }
 
     @Test
-    public void parseUtils() throws IOException, ParseException {
+    void parseUtils() throws IOException {
         parse("com/github/javaparser/utils/ClassUtils");
         parse("com/github/javaparser/utils/Pair");
     }
 
     @Test
-    public void parseAllOtherNodes() throws IOException, ParseException {
+    void parseAllOtherNodes() throws IOException {
         parse("com/github/javaparser/JavaParser");
         parse("com/github/javaparser/ParseProblemException");
         parse("com/github/javaparser/ParseResult");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnnotationsResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnnotationsResolutionTest.java
new file mode 100644
index 0000000..f427514
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnnotationsResolutionTest.java
@@ -0,0 +1,240 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.AnnotationExpr;
+import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
+import com.github.javaparser.ast.expr.NormalAnnotationExpr;
+import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
+import com.github.javaparser.resolution.declarations.ResolvedAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests resolution of annotation expressions.
+ *
+ * @author Malte Skoruppa
+ */
+class AnnotationsResolutionTest extends AbstractResolutionTest {
+
+    @BeforeAll
+    static void configureSymbolSolver() throws IOException {
+        // configure symbol solver before parsing
+        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
+        typeSolver.add(new ReflectionTypeSolver());
+        typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
+    }
+
+    @AfterAll
+    static void unConfigureSymbolSolver() {
+        // unconfigure symbol solver so as not to potentially disturb tests in other classes
+        StaticJavaParser.getConfiguration().setSymbolResolver(null);
+    }
+
+    @Test
+    void solveJavaParserMarkerAnnotation() {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CA");
+        MarkerAnnotationExpr annotationExpr = (MarkerAnnotationExpr) clazz.getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("foo.bar.MyAnnotation", resolved.getQualifiedName());
+        assertEquals("foo.bar", resolved.getPackageName());
+        assertEquals("MyAnnotation", resolved.getName());
+    }
+
+    @Test
+    void solveJavaParserSingleMemberAnnotation() {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CC");
+        SingleMemberAnnotationExpr annotationExpr = (SingleMemberAnnotationExpr) clazz.getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("foo.bar.MyAnnotationWithSingleValue", resolved.getQualifiedName());
+        assertEquals("foo.bar", resolved.getPackageName());
+        assertEquals("MyAnnotationWithSingleValue", resolved.getName());
+    }
+
+    @Test
+    void solveJavaParserNormalAnnotation() {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CD");
+        NormalAnnotationExpr annotationExpr = (NormalAnnotationExpr) clazz.getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("foo.bar.MyAnnotationWithElements", resolved.getQualifiedName());
+        assertEquals("foo.bar", resolved.getPackageName());
+        assertEquals("MyAnnotationWithElements", resolved.getName());
+    }
+
+    @Test
+    void solveReflectionMarkerAnnotation() {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CA");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "equals");
+        MarkerAnnotationExpr annotationExpr = (MarkerAnnotationExpr) method.getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("java.lang.Override", resolved.getQualifiedName());
+        assertEquals("java.lang", resolved.getPackageName());
+        assertEquals("Override", resolved.getName());
+    }
+
+    @Test
+    void solveReflectionSingleMemberAnnotation() {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CC");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
+        SingleMemberAnnotationExpr annotationExpr =
+                (SingleMemberAnnotationExpr) method.getBody().get().getStatement(0)
+                        .asExpressionStmt().getExpression()
+                        .asVariableDeclarationExpr().getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("java.lang.SuppressWarnings", resolved.getQualifiedName());
+        assertEquals("java.lang", resolved.getPackageName());
+        assertEquals("SuppressWarnings", resolved.getName());
+    }
+
+    @Test
+    void solveJavassistMarkerAnnotation() throws IOException {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CA");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "setUp");
+        MarkerAnnotationExpr annotationExpr = (MarkerAnnotationExpr) method.getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("org.junit.Before", resolved.getQualifiedName());
+        assertEquals("org.junit", resolved.getPackageName());
+        assertEquals("Before", resolved.getName());
+    }
+
+    @Test
+    void solveJavassistSingleMemberAnnotation() throws IOException {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CC");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "testSomething");
+        SingleMemberAnnotationExpr annotationExpr = (SingleMemberAnnotationExpr) method.getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("org.junit.Ignore", resolved.getQualifiedName());
+        assertEquals("org.junit", resolved.getPackageName());
+        assertEquals("Ignore", resolved.getName());
+    }
+
+    @Test
+    void solveJavassistNormalAnnotation() throws IOException {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CD");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "testSomethingElse");
+        NormalAnnotationExpr annotationExpr = (NormalAnnotationExpr) method.getAnnotation(0);
+
+        // resolve annotation expression
+        ResolvedAnnotationDeclaration resolved = annotationExpr.resolve();
+
+        // check that the expected annotation declaration equals the resolved annotation declaration
+        assertEquals("org.junit.Test", resolved.getQualifiedName());
+        assertEquals("org.junit", resolved.getPackageName());
+        assertEquals("Test", resolved.getName());
+    }
+
+    @Test
+    void solveJavaParserMetaAnnotations() {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CA");
+        AnnotationExpr annotationExpr = clazz.getAnnotation(0);
+
+        // resolve annotation expression @MyAnnotation
+        JavaParserAnnotationDeclaration resolved = (JavaParserAnnotationDeclaration) annotationExpr.resolve();
+
+        // check that the annotation @MyAnnotation has the annotations @Target and @Retention, but not @Documented
+        assertEquals("foo.bar.MyAnnotation", resolved.getQualifiedName());
+        assertTrue(resolved.hasDirectlyAnnotation("java.lang.annotation.Target"));
+        assertTrue(resolved.hasDirectlyAnnotation("java.lang.annotation.Retention"));
+        assertFalse(resolved.hasDirectlyAnnotation("java.lang.annotation.Documented"));
+    }
+
+    @Test
+    void solveReflectionMetaAnnotations() {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CA");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "equals");
+        MarkerAnnotationExpr annotationExpr = (MarkerAnnotationExpr) method.getAnnotation(0);
+
+        // resolve annotation expression @Override
+        ReflectionAnnotationDeclaration resolved = (ReflectionAnnotationDeclaration) annotationExpr.resolve();
+
+        // check that the annotation @Override has the annotations @Target and @Retention, but not @Documented
+        assertEquals("java.lang.Override", resolved.getQualifiedName());
+        assertTrue(resolved.hasDirectlyAnnotation("java.lang.annotation.Target"));
+        assertTrue(resolved.hasDirectlyAnnotation("java.lang.annotation.Retention"));
+        assertFalse(resolved.hasDirectlyAnnotation("java.lang.annotation.Documented"));
+    }
+
+    @Test
+    void solveJavassistMetaAnnotation() throws IOException {
+        // parse compilation unit and get annotation expression
+        CompilationUnit cu = parseSample("Annotations");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "CD");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "testSomethingElse");
+        AnnotationExpr annotationExpr = method.getAnnotation(0);
+
+        // resolve annotation expression @Test
+        JavassistAnnotationDeclaration resolved = (JavassistAnnotationDeclaration) annotationExpr.resolve();
+
+        // check that the annotation @Test has the annotations @Target and @Retention, but not @Documented
+        assertEquals("org.junit.Test", resolved.getQualifiedName());
+        assertTrue(resolved.hasDirectlyAnnotation("java.lang.annotation.Target"));
+        assertTrue(resolved.hasDirectlyAnnotation("java.lang.annotation.Retention"));
+        assertFalse(resolved.hasDirectlyAnnotation("java.lang.annotation.Documented"));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnonymousClassesResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnonymousClassesResolutionTest.java
new file mode 100644
index 0000000..68b3ba4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/AnonymousClassesResolutionTest.java
@@ -0,0 +1,62 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class AnonymousClassesResolutionTest extends AbstractResolutionTest {
+
+    @BeforeAll
+    static void configureSymbolSolver() throws IOException {
+        // configure symbol solver before parsing
+        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
+        typeSolver.add(new ReflectionTypeSolver());
+        MemoryTypeSolver memoryTypeSolver = new MemoryTypeSolver();
+
+        ResolvedReferenceTypeDeclaration cd = mock(ResolvedReferenceTypeDeclaration.class);
+        when(cd.asReferenceType()).thenReturn(cd);
+        memoryTypeSolver.addDeclaration("org.springframework.transaction.support.TransactionCallbackWithoutResult",
+                cd);
+
+        typeSolver.add(memoryTypeSolver);
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver));
+    }
+
+    @AfterAll
+    static void unConfigureSymbolSolver() {
+        // unconfigure symbol solver so as not to potentially disturb tests in other classes
+        StaticJavaParser.getConfiguration().setSymbolResolver(null);
+    }
+
+    // See #1703
+    @Test
+    void solveAnonymousClassMethodClass() {
+        CompilationUnit cu = parseSample("AnonymousClassMethodClass");
+
+        cu.accept(new VoidVisitorAdapter<Object>() {
+
+
+            @Override
+            public void visit(MethodCallExpr m, Object arg) {
+                m.getScope().get().asNameExpr().resolve();
+            }
+        }, null);
+
+    }
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ArrayExprTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ArrayExprTest.java
index 92b9733..b2743eb 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ArrayExprTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ArrayExprTest.java
@@ -1,26 +1,49 @@
 package com.github.javaparser.symbolsolver.resolution;
 
 import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StringProvider;
+import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * See issue #17
  */
-public class ArrayExprTest {
+class ArrayExprTest {
 
     @Test
-    public void verifyAnArrayAccessExprTypeIsCalculatedProperly() {
+    void verifyAnArrayAccessExprTypeIsCalculatedProperly() {
         String code = "class A { String[] arrSQL; String toExamine = arrSQL[1]; }";
-        FieldDeclaration field = JavaParser.parse(code).getClassByName("A").get().getFieldByName("toExamine").get();
+        FieldDeclaration field = parse(code).getClassByName("A").get().getFieldByName("toExamine").get();
 
         ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(field.getVariables().get(0).getInitializer().get());
-        assertEquals(true, type.isReferenceType());
+        assertTrue(type.isReferenceType());
         assertEquals("java.lang.String", type.asReferenceType().getQualifiedName());
     }
+
+    @Test
+    void arrayLengthValueDeclaration() {
+        String code = "class A { String[] arrSQL; int l = arrSQL.length; }";
+        ParserConfiguration parserConfiguration = new ParserConfiguration();
+        parserConfiguration.setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+        CompilationUnit cu = new JavaParser(parserConfiguration).parse(ParseStart.COMPILATION_UNIT, new StringProvider(code)).getResult().get();
+        FieldDeclaration field = cu.getClassByName("A").get().getFieldByName("l").get();
+
+        ResolvedValueDeclaration resolvedValueDeclaration = ((FieldAccessExpr)field.getVariables().get(0).getInitializer().get()).resolve();
+        assertEquals("length", resolvedValueDeclaration.getName());
+        assertEquals(ResolvedPrimitiveType.INT, resolvedValueDeclaration.getType());
+    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ConstructorsResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ConstructorsResolutionTest.java
new file mode 100644
index 0000000..b972035
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ConstructorsResolutionTest.java
@@ -0,0 +1,142 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
+import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
+import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserConstructorDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ConstructorsResolutionTest extends AbstractResolutionTest {
+
+    @AfterEach
+    void resetConfiguration() {
+        StaticJavaParser.setConfiguration(new ParserConfiguration());
+    }
+
+    @Test
+    void solveNormalConstructor() {
+        CompilationUnit cu = parseSample("ConstructorCalls");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ConstructorCalls");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "testNormalConstructor");
+        ObjectCreationExpr objectCreationExpr = method.getBody().get().getStatements().get(0)
+                .asExpressionStmt().getExpression().asObjectCreationExpr();
+
+        SymbolReference<ResolvedConstructorDeclaration> ref =
+                JavaParserFacade.get(new ReflectionTypeSolver()).solve(objectCreationExpr);
+        ConstructorDeclaration actualConstructor =
+                ((JavaParserConstructorDeclaration) ref.getCorrespondingDeclaration()).getWrappedNode();
+
+        ClassOrInterfaceDeclaration otherClazz = Navigator.demandClass(cu, "OtherClass");
+        ConstructorDeclaration expectedConstructor = Navigator.demandConstructor(otherClazz, 0);
+
+        assertEquals(expectedConstructor, actualConstructor);
+    }
+
+    @Test
+    void solveInnerClassConstructor() {
+        CompilationUnit cu = parseSample("ConstructorCalls");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ConstructorCalls");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "testInnerClassConstructor");
+        ObjectCreationExpr objectCreationExpr = method.getBody().get().getStatements().get(1)
+                .asExpressionStmt().getExpression().asObjectCreationExpr();
+
+        SymbolReference<ResolvedConstructorDeclaration> ref =
+                JavaParserFacade.get(new ReflectionTypeSolver()).solve(objectCreationExpr);
+        ConstructorDeclaration actualConstructor =
+                ((JavaParserConstructorDeclaration) ref.getCorrespondingDeclaration()).getWrappedNode();
+
+        ClassOrInterfaceDeclaration innerClazz = Navigator.demandClass(cu, "OtherClass.InnerClass");
+        ConstructorDeclaration expectedConstructor = Navigator.demandConstructor(innerClazz, 0);
+
+        assertEquals(expectedConstructor, actualConstructor);
+    }
+
+    @Test
+    void solveInnerClassConstructorWithNewScope() {
+        CompilationUnit cu = parseSample("ConstructorCalls");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ConstructorCalls");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "testInnerClassConstructorWithNewScope");
+        ObjectCreationExpr objectCreationExpr = method.getBody().get().getStatements().get(0)
+                .asExpressionStmt().getExpression().asObjectCreationExpr();
+
+        SymbolReference<ResolvedConstructorDeclaration> ref =
+                JavaParserFacade.get(new ReflectionTypeSolver()).solve(objectCreationExpr);
+        ConstructorDeclaration actualConstructor =
+                ((JavaParserConstructorDeclaration) ref.getCorrespondingDeclaration()).getWrappedNode();
+
+        ClassOrInterfaceDeclaration innerClazz = Navigator.demandClass(cu, "OtherClass.InnerClass");
+        ConstructorDeclaration expectedConstructor = Navigator.demandConstructor(innerClazz, 0);
+
+        assertEquals(expectedConstructor, actualConstructor);
+    }
+
+    @Test
+    void solveInnerInnerClassConstructor() {
+        CompilationUnit cu = parseSample("ConstructorCalls");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ConstructorCalls");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "testInnerInnerClassConstructor");
+        ObjectCreationExpr objectCreationExpr = method.getBody().get().getStatements().get(0)
+                .asExpressionStmt().getExpression().asObjectCreationExpr();
+
+        SymbolReference<ResolvedConstructorDeclaration> ref =
+                JavaParserFacade.get(new ReflectionTypeSolver()).solve(objectCreationExpr);
+        ConstructorDeclaration actualConstructor =
+                ((JavaParserConstructorDeclaration) ref.getCorrespondingDeclaration()).getWrappedNode();
+
+        ClassOrInterfaceDeclaration innerClazz = Navigator.demandClass(cu, "OtherClass.InnerClass.InnerInnerClass");
+        ConstructorDeclaration expectedConstructor = Navigator.demandConstructor(innerClazz, 0);
+
+        assertEquals(expectedConstructor, actualConstructor);
+    }
+
+    @Test
+    void solveEnumConstructor() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        CompilationUnit cu = parseSample("ConstructorCallsEnum");
+        EnumDeclaration enumDeclaration = Navigator.demandEnum(cu, "ConstructorCallsEnum");
+        ConstructorDeclaration constructor = (ConstructorDeclaration) enumDeclaration.getChildNodes().get(3);
+
+        ResolvedConstructorDeclaration resolvedConstructor = constructor.resolve();
+
+        assertEquals("ConstructorCallsEnum", resolvedConstructor.declaringType().getName());
+        assertEquals(1, resolvedConstructor.getNumberOfParams());
+        assertEquals("i", resolvedConstructor.getParam(0).getName());
+        assertEquals(ResolvedPrimitiveType.INT, resolvedConstructor.getParam(0).getType());
+    }
+
+    @Test
+    void solveNonPublicParentConstructorReflection() {
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        CompilationUnit cu = parseSample("ReflectionTypeSolverConstructorResolution");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ReflectionTypeSolverConstructionResolution");
+        ConstructorDeclaration constructorDeclaration = Navigator.demandConstructor(clazz, 0);
+        ExplicitConstructorInvocationStmt stmt =
+                (ExplicitConstructorInvocationStmt) constructorDeclaration.getBody().getStatement(0);
+
+        ResolvedConstructorDeclaration cd = stmt.resolve();
+
+        assertEquals(1, cd.getNumberOfParams());
+        assertEquals(ResolvedPrimitiveType.INT, cd.getParam(0).getType());
+        assertEquals("java.lang.AbstractStringBuilder", cd.declaringType().getQualifiedName());
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ContextTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ContextTest.java
index 45cc56e..f2da195 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ContextTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ContextTest.java
@@ -16,50 +16,55 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseException;
+import com.github.javaparser.*;
 import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.expr.AssignExpr;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.*;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Path;
 import java.util.Collections;
+import java.util.List;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-public class ContextTest extends AbstractTest {
+class ContextTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolver = new CombinedTypeSolver(new MemoryTypeSolver(), new ReflectionTypeSolver());
 
     private CompilationUnit parseSample(String sampleName) {
         InputStream is = ContextTest.class.getClassLoader().getResourceAsStream(sampleName + ".java.txt");
-        return JavaParser.parse(is);
+        return StaticJavaParser.parse(is);
     }
 
     @Test
-    public void resolveDeclaredFieldReference() {
+    void resolveDeclaredFieldReference() {
         CompilationUnit cu = parseSample("ReferencesToField");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "ReferencesToField");
         MethodDeclaration method1 = Navigator.demandMethod(referencesToField, "method1");
@@ -69,13 +74,13 @@
         SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
         SymbolReference symbolReference = symbolSolver.solveSymbol("i", assignExpr.getTarget());
 
-        assertEquals(true, symbolReference.isSolved());
+        assertTrue(symbolReference.isSolved());
         assertEquals("i", symbolReference.getCorrespondingDeclaration().getName());
-        assertEquals(true, symbolReference.getCorrespondingDeclaration().isField());
+        assertTrue(symbolReference.getCorrespondingDeclaration().isField());
     }
 
     @Test
-    public void resolveInheritedFieldReference() {
+    void resolveInheritedFieldReference() {
         CompilationUnit cu = parseSample("ReferencesToField");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "ReferencesToFieldExtendingClass");
         MethodDeclaration method1 = Navigator.demandMethod(referencesToField, "method2");
@@ -85,13 +90,13 @@
         SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
         SymbolReference symbolReference = symbolSolver.solveSymbol("i", assignExpr.getTarget());
 
-        assertEquals(true, symbolReference.isSolved());
+        assertTrue(symbolReference.isSolved());
         assertEquals("i", symbolReference.getCorrespondingDeclaration().getName());
-        assertEquals(true, symbolReference.getCorrespondingDeclaration().isField());
+        assertTrue(symbolReference.getCorrespondingDeclaration().isField());
     }
 
     @Test
-    public void resolveParameterReference() {
+    void resolveParameterReference() {
         CompilationUnit cu = parseSample("ReferencesToParameter");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "ReferenceToParameter");
         MethodDeclaration method1 = Navigator.demandMethod(referencesToField, "aMethod");
@@ -100,13 +105,13 @@
         SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
         SymbolReference symbolReference = symbolSolver.solveSymbol("foo", foo);
 
-        assertEquals(true, symbolReference.isSolved());
+        assertTrue(symbolReference.isSolved());
         assertEquals("foo", symbolReference.getCorrespondingDeclaration().getName());
-        assertEquals(true, symbolReference.getCorrespondingDeclaration().isParameter());
+        assertTrue(symbolReference.getCorrespondingDeclaration().isParameter());
     }
 
     @Test
-    public void resolveReferenceToImportedType() {
+    void resolveReferenceToImportedType() {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "findType");
@@ -123,13 +128,13 @@
 
         SymbolReference<? extends ResolvedTypeDeclaration> ref = symbolSolver.solveType("CompilationUnit", param);
 
-        assertEquals(true, ref.isSolved());
+        assertTrue(ref.isSolved());
         assertEquals("CompilationUnit", ref.getCorrespondingDeclaration().getName());
         assertEquals("com.github.javaparser.ast.CompilationUnit", ref.getCorrespondingDeclaration().getQualifiedName());
     }
 
     @Test
-    public void resolveReferenceUsingQualifiedName() {
+    void resolveReferenceUsingQualifiedName() {
         CompilationUnit cu = parseSample("Navigator2");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "findType");
@@ -147,13 +152,13 @@
         
         SymbolReference<? extends ResolvedTypeDeclaration> ref = symbolSolver.solveType("com.github.javaparser.ast.CompilationUnit", param);
 
-        assertEquals(true, ref.isSolved());
+        assertTrue(ref.isSolved());
         assertEquals("CompilationUnit", ref.getCorrespondingDeclaration().getName());
         assertEquals("com.github.javaparser.ast.CompilationUnit", ref.getCorrespondingDeclaration().getQualifiedName());
     }
 
     @Test
-    public void resolveReferenceToClassesInTheSamePackage() {
+    void resolveReferenceToClassesInTheSamePackage() {
         CompilationUnit cu = parseSample("Navigator3");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "findType");
@@ -170,13 +175,13 @@
 
         SymbolReference<? extends ResolvedTypeDeclaration> ref = symbolSolver.solveType("CompilationUnit", param);
 
-        assertEquals(true, ref.isSolved());
+        assertTrue(ref.isSolved());
         assertEquals("CompilationUnit", ref.getCorrespondingDeclaration().getName());
         assertEquals("my.packagez.CompilationUnit", ref.getCorrespondingDeclaration().getQualifiedName());
     }
 
     @Test
-    public void resolveReferenceToClassInJavaLang() {
+    void resolveReferenceToClassInJavaLang() {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "findType");
@@ -194,19 +199,19 @@
 
         SymbolReference<? extends ResolvedTypeDeclaration> ref = symbolSolver.solveType("String", param);
 
-        assertEquals(true, ref.isSolved());
+        assertTrue(ref.isSolved());
         assertEquals("String", ref.getCorrespondingDeclaration().getName());
         assertEquals("java.lang.String", ref.getCorrespondingDeclaration().getQualifiedName());
     }
 
     @Test
-    public void resolveReferenceToMethod() throws ParseException, IOException {
+    void resolveReferenceToMethod() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "findType");
         MethodCallExpr callToGetTypes = Navigator.findMethodCall(method, "getTypes").get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver(true));
         SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
 
@@ -219,13 +224,13 @@
     }
 
     @Test
-    public void resolveCascadeOfReferencesToMethod() throws ParseException, IOException {
+    void resolveCascadeOfReferencesToMethod() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "findType");
         MethodCallExpr callToStream = Navigator.findMethodCall(method, "stream").get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new ReflectionTypeSolver(true));
         SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
         MethodUsage ref = symbolSolver.solveMethod("stream", Collections.emptyList(), callToStream);
@@ -235,14 +240,14 @@
     }
 
     @Test
-    public void resolveReferenceToMethodCalledOnArrayAccess() {
+    void resolveReferenceToMethodCalledOnArrayAccess() {
         CompilationUnit cu = parseSample("ArrayAccess");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ArrayAccess");
         MethodDeclaration method = Navigator.demandMethod(clazz, "access");
         MethodCallExpr callToTrim = Navigator.findMethodCall(method, "trim").get();
 
-        File src = adaptPath(new File("src/test/resources"));
-        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(src));
+        Path src = adaptPath("src/test/resources");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(src, new LeanParserConfiguration()));
         SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
         MethodUsage ref = symbolSolver.solveMethod("trim", Collections.emptyList(), callToTrim);
 
@@ -251,7 +256,7 @@
     }
 
     @Test
-    public void resolveReferenceToJreType() {
+    void resolveReferenceToJreType() {
         CompilationUnit cu = parseSample("NavigatorSimplified");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
@@ -264,7 +269,7 @@
     }
 
     @Test
-    public void resolveReferenceToMethodWithLambda() {
+    void resolveReferenceToMethodWithLambda() {
         CompilationUnit cu = parseSample("NavigatorSimplified");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
@@ -279,7 +284,7 @@
     }
 
     @Test
-    public void resolveReferenceToLambdaParamBase() {
+    void resolveReferenceToLambdaParamBase() {
         CompilationUnit cu = parseSample("NavigatorSimplified");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
@@ -293,7 +298,7 @@
     }
 
     @Test
-    public void resolveReferenceToLambdaParamSimplified() {
+    void resolveReferenceToLambdaParamSimplified() {
         CompilationUnit cu = parseSample("NavigatorSimplified");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
@@ -308,13 +313,13 @@
     }
 
     @Test
-    public void resolveGenericReturnTypeOfMethodInJar() throws ParseException, IOException {
+    void resolveGenericReturnTypeOfMethodInJar() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
         MethodCallExpr call = Navigator.findMethodCall(method, "getTypes").get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
         MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
 
@@ -325,13 +330,103 @@
     }
 
     @Test
-    public void resolveTypeUsageOfFirstMethodInGenericClass() throws ParseException, IOException {
+    void resolveCompoundGenericReturnTypeOfMethodInJar() throws IOException {
+        CompilationUnit cu = parseSample("GenericClassNavigator");
+        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericClassNavigator");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "doubleTyped");
+        MethodCallExpr call = Navigator.findMethodCall(method, "genericMethodWithDoubleTypedReturnType").get();
+
+        Path pathToJar = adaptPath("src/test/resources/javassist_generics/generics.jar");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
+        MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
+
+        assertEquals("genericMethodWithDoubleTypedReturnType", methodUsage.getName());
+        assertEquals("java.util.Map<T, V>", methodUsage.returnType().describe());
+    }
+
+    @Test
+    void resolveNestedGenericReturnTypeOfMethodInJar() throws IOException {
+        CompilationUnit cu = parseSample("GenericClassNavigator");
+        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericClassNavigator");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "nestedTyped");
+        MethodCallExpr call = Navigator.findMethodCall(method, "genericMethodWithNestedReturnType").get();
+
+        Path pathToJar = adaptPath("src/test/resources/javassist_generics/generics.jar");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
+        MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
+
+        assertEquals("genericMethodWithNestedReturnType", methodUsage.getName());
+        assertEquals("java.util.List<java.util.List<T>>", methodUsage.returnType().describe());
+    }
+
+    @Test
+    void resolveSimpleGenericReturnTypeOfMethodInJar() throws IOException {
+        CompilationUnit cu = parseSample("GenericClassNavigator");
+        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericClassNavigator");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "simple");
+        MethodCallExpr call = Navigator.findMethodCall(method, "get").get();
+
+        Path pathToJar = adaptPath("src/test/resources/javassist_generics/generics.jar");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
+        MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
+
+        assertEquals("get", methodUsage.getName());
+        assertEquals("java.util.List<java.util.List<java.lang.String>>", methodUsage.returnType().describe());
+    }
+
+    @Test
+    void resolveGenericReturnTypeFromInputParam() throws IOException {
+        CompilationUnit cu = parseSample("GenericClassNavigator");
+        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericClassNavigator");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "input");
+        MethodCallExpr call = Navigator.findMethodCall(method, "copy").get();
+
+        Path pathToJar = adaptPath("src/test/resources/javassist_generics/generics.jar");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
+        MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
+
+        assertEquals("copy", methodUsage.getName());
+        assertEquals("javaparser.GenericClass<java.util.List<java.lang.String>>", methodUsage.returnType().describe());
+    }
+
+    @Test
+    void resolveComplexGenericReturnType() throws IOException {
+        CompilationUnit cu = parseSample("GenericClassNavigator");
+        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericClassNavigator");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "complex");
+        MethodCallExpr call = Navigator.findMethodCall(method, "complexGenerics").get();
+
+        Path pathToJar = adaptPath("src/test/resources/javassist_generics/generics.jar");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
+        MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
+
+        assertEquals("complexGenerics", methodUsage.getName());
+        assertEquals("T", methodUsage.returnType().describe());
+    }
+
+    @Test
+    void resolveDoubleNestedClassType() throws IOException {
+        CompilationUnit cu = parseSample("GenericClassNavigator");
+        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericClassNavigator");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "nestedTypes");
+        MethodCallExpr call = Navigator.findMethodCall(method, "asList").get();
+
+        Path pathToJar = adaptPath("src/test/resources/javassist_generics/generics.jar");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
+        MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
+
+        assertEquals("asList", methodUsage.getName());
+        assertEquals("java.util.List<javaparser.GenericClass.Bar.NestedBar>", methodUsage.getParamType(0).describe());
+    }
+
+    @Test
+    void resolveTypeUsageOfFirstMethodInGenericClass() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
         MethodCallExpr callToGetTypes = Navigator.findMethodCall(method, "getTypes").get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
         MethodUsage filterUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(callToGetTypes);
 
@@ -341,13 +436,13 @@
     }
 
     @Test
-    public void resolveTypeUsageOfMethodInGenericClass() throws ParseException, IOException {
+    void resolveTypeUsageOfMethodInGenericClass() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
         MethodCallExpr callToStream = Navigator.findMethodCall(method, "stream").get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
         MethodUsage filterUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(callToStream);
 
@@ -355,13 +450,13 @@
     }
 
     @Test
-    public void resolveTypeUsageOfCascadeMethodInGenericClass() throws ParseException, IOException {
+    void resolveTypeUsageOfCascadeMethodInGenericClass() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
         MethodCallExpr callToFilter = Navigator.findMethodCall(method, "filter").get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
         MethodUsage filterUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(callToFilter);
 
@@ -369,14 +464,14 @@
     }
 
     @Test
-    public void resolveLambdaType() throws ParseException, IOException {
+    void resolveLambdaType() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
         MethodCallExpr callToFilter = Navigator.findMethodCall(method, "filter").get();
         Expression lambdaExpr = callToFilter.getArguments().get(0);
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
         ResolvedType typeOfLambdaExpr = JavaParserFacade.get(typeSolver).getType(lambdaExpr);
 
@@ -384,14 +479,14 @@
     }
 
     @Test
-    public void resolveReferenceToLambdaParam() throws ParseException, IOException {
+    void resolveReferenceToLambdaParam() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
         MethodCallExpr callToGetName = Navigator.findMethodCall(method, "getName").get();
         Expression referenceToT = callToGetName.getScope().get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
         ResolvedType typeOfT = JavaParserFacade.get(typeSolver).getType(referenceToT);
 
@@ -399,13 +494,13 @@
     }
 
     @Test
-    public void resolveReferenceToCallOnLambdaParam() throws ParseException, IOException {
+    void resolveReferenceToCallOnLambdaParam() throws IOException {
         CompilationUnit cu = parseSample("Navigator");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Navigator");
         MethodDeclaration method = Navigator.demandMethod(clazz, "findType");
         MethodCallExpr callToGetName = Navigator.findMethodCall(method, "getName").get();
 
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
         MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(callToGetName);
 
@@ -414,7 +509,7 @@
     }
 
     @Test
-    public void resolveReferenceToOverloadMethodWithNullParam() {
+    void resolveReferenceToOverloadMethodWithNullParam() {
         CompilationUnit cu = parseSample("OverloadedMethods");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "OverloadedMethods");
         MethodDeclaration method = Navigator.demandMethod(clazz, "m1");
@@ -429,7 +524,7 @@
     }
 
     @Test
-    public void resolveReferenceToOverloadMethodFindStricter() {
+    void resolveReferenceToOverloadMethodFindStricter() {
         CompilationUnit cu = parseSample("OverloadedMethods");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "OverloadedMethods");
         MethodDeclaration method = Navigator.demandMethod(clazz, "m2");
@@ -444,13 +539,28 @@
     }
 
     @Test
-    public void resolveInheritedMethodFromInterface() {
+    void resolveReferenceToMethodWithGenericArrayTypeParam() {
+        CompilationUnit cu = parseSample("GenericArrayMethodArgument");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericArrayMethodArgument");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
+        MethodCallExpr call = Navigator.findMethodCall(method, "foo").get();
+
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        MethodUsage ref = JavaParserFacade.get(typeSolver).solveMethodAsUsage(call);
+
+        assertEquals("foo", ref.getName());
+        assertEquals(1, ref.getNoParams());
+        assertEquals("java.lang.String[]", ref.getParamType(0).describe());
+    }
+
+    @Test
+    void resolveInheritedMethodFromInterface() {
         CompilationUnit cu = parseSample("InterfaceInheritance");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Test");
         MethodDeclaration method = Navigator.demandMethod(clazz, "test");
         MethodCallExpr call = Navigator.findMethodCall(method, "foobar").get();
 
-        File src = adaptPath(new File("src/test/resources"));
+        Path src = adaptPath("src/test/resources");
         TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(src));
         ResolvedType type = JavaParserFacade.get(typeSolver).getType(call);
 
@@ -458,7 +568,7 @@
     }
 
     @Test
-    public void resolveReferenceToOverloadMethodFindOnlyCompatible() {
+    void resolveReferenceToOverloadMethodFindOnlyCompatible() {
         CompilationUnit cu = parseSample("OverloadedMethods");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "OverloadedMethods");
         MethodDeclaration method = Navigator.demandMethod(clazz, "m3");
@@ -472,4 +582,181 @@
         assertEquals("java.lang.Object", ref.getParamTypes().get(0).describe());
     }
 
+    private <PS extends Node> PS parse(String code, ParseStart<PS> parseStart) {
+        ParserConfiguration parserConfiguration = new ParserConfiguration();
+        parserConfiguration.setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_10);
+        ParseResult<PS> parseResult = new JavaParser(parserConfiguration).parse(parseStart, new StringProvider(code));
+        if (!parseResult.isSuccessful()) {
+            parseResult.getProblems().forEach(p -> System.out.println("ERR: " + p));
+        }
+        assertTrue(parseResult.isSuccessful());
+        PS root = parseResult.getResult().get();
+        return root;
+    }
+
+    @Test
+    void localVariableDeclarationInScope() {
+        String name = "a";
+        CompilationUnit cu = parse("class A { void foo() {\n" +
+                "SomeClass a; a.aField;" + "\n" +
+                "} }", ParseStart.COMPILATION_UNIT);
+
+        // The block statement expose to the 2nd statement the local var
+        BlockStmt blockStmt = cu.findAll(BlockStmt.class).get(0);
+        Context context1 = JavaParserFactory.getContext(blockStmt, typeSolver);
+        assertEquals(1, context1.localVariablesExposedToChild(blockStmt.getStatement(1)).size());
+
+        Node nameNode = cu.findAll(NameExpr.class).get(0);
+        Context context = JavaParserFactory.getContext(nameNode, typeSolver);
+        assertTrue(context.localVariableDeclarationInScope(name).isPresent());
+    }
+
+    //
+    // Testing JLS 6.3 Scope of a Declaration
+    //
+
+    // The scope of a formal parameter of a method (§8.4.1), constructor (§8.8.1), or lambda expression (§15.27) is the
+    // entire body of the method, constructor, or lambda expression.
+
+    private void assertNoParamsExposedToChildInContextNamed(Node parent, Node child, String paramName) {
+        assertNumberOfParamsExposedToChildInContextNamed(parent, child, paramName, 0, "the element is exposed and it should not");
+    }
+
+    private void assertOneParamExposedToChildInContextNamed(Node parent, Node child, String paramName) {
+        assertNumberOfParamsExposedToChildInContextNamed(parent, child, paramName, 1, "the element is not exposed as expected");
+    }
+
+    private void assertNumberOfParamsExposedToChildInContextNamed(Node parent, Node child, String paramName,
+                                                                  int expectedNumber, String message) {
+        assertEquals(expectedNumber, JavaParserFactory.getContext(parent, typeSolver)
+                .parametersExposedToChild(child).stream().filter(p -> p.getNameAsString().equals(paramName)).count(), message);
+    }
+
+    private void assertNoVarsExposedToChildInContextNamed(Node parent, Node child, String paramName) {
+        assertNumberOfVarsExposedToChildInContextNamed(parent, child, paramName, 0, "the element is exposed and it should not");
+    }
+
+    private void assertOneVarExposedToChildInContextNamed(Node parent, Node child, String paramName) {
+        assertNumberOfVarsExposedToChildInContextNamed(parent, child, paramName, 1, "the element is not exposed as expected");
+    }
+
+    private void assertNumberOfVarsExposedToChildInContextNamed(Node parent, Node child, String paramName,
+                                                                  int expectedNumber, String message) {
+        List<VariableDeclarator> vars = JavaParserFactory.getContext(parent, typeSolver)
+                .localVariablesExposedToChild(child);
+        assertEquals(expectedNumber, vars.stream().filter(p -> p.getNameAsString().equals(paramName)).count(), message);
+    }
+
+    @Test
+    void parametersExposedToChildForMethod() {
+        MethodDeclaration method = parse("void foo(int myParam) { aCall(); }",
+                ParseStart.CLASS_BODY).asMethodDeclaration();
+        assertOneParamExposedToChildInContextNamed(method, method.getBody().get(), "myParam");
+        assertNoParamsExposedToChildInContextNamed(method, method.getType(), "myParam");
+        assertNoParamsExposedToChildInContextNamed(method, method.getParameter(0), "myParam");
+    }
+
+    @Test
+    void parametersExposedToChildForConstructor() {
+        ConstructorDeclaration constructor = parse("Foo(int myParam) { aCall(); }",
+                ParseStart.CLASS_BODY).asConstructorDeclaration();
+        assertOneParamExposedToChildInContextNamed(constructor, constructor.getBody(), "myParam");
+        assertNoParamsExposedToChildInContextNamed(constructor, constructor.getParameter(0), "myParam");
+    }
+
+    @Test
+    void parametersExposedToChildForLambda() {
+        LambdaExpr lambda = (LambdaExpr)parse("Object myLambda = (myParam) -> myParam * 2;",
+                ParseStart.STATEMENT).asExpressionStmt().getExpression().asVariableDeclarationExpr()
+                .getVariables().get(0).getInitializer().get();
+        assertOneParamExposedToChildInContextNamed(lambda, lambda.getBody(), "myParam");
+        assertNoParamsExposedToChildInContextNamed(lambda, lambda.getParameter(0), "myParam");
+    }
+
+    // The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration
+    // appears, starting with its own initializer and including any further declarators to the right in the local
+    // variable declaration statement.
+
+    @Test
+    void localVariablesExposedToChildWithinABlock() {
+        BlockStmt blockStmt = parse("{ preStatement(); int a = 1, b = 2; otherStatement(); }",
+                ParseStart.STATEMENT).asBlockStmt();
+        assertNoVarsExposedToChildInContextNamed(blockStmt, blockStmt.getStatement(0), "a");
+        assertNoVarsExposedToChildInContextNamed(blockStmt, blockStmt.getStatement(0), "b");
+        assertOneVarExposedToChildInContextNamed(blockStmt, blockStmt.getStatement(2), "a");
+        assertOneVarExposedToChildInContextNamed(blockStmt, blockStmt.getStatement(2), "b");
+
+        VariableDeclarationExpr varDecl = blockStmt.getStatement(1).asExpressionStmt().getExpression()
+                .asVariableDeclarationExpr();
+        VariableDeclarator varA = varDecl.getVariables().get(0);
+        VariableDeclarator varB = varDecl.getVariables().get(1);
+        assertOneVarExposedToChildInContextNamed(varA,
+                varA.getInitializer().get(), "a");
+        assertOneVarExposedToChildInContextNamed(varDecl,
+                varB, "a");
+        assertNoVarsExposedToChildInContextNamed(varDecl,
+                varA, "b");
+    }
+
+    // The scope of a local variable declared in the ForInit part of a basic for statement (§14.14.1) includes all of the following:
+    // * Its own initializer
+    // * Any further declarators to the right in the ForInit part of the for statement
+    // * The Expression and ForUpdate parts of the for statement
+    // * The contained Statement
+
+    @Test
+    void localVariablesExposedToChildWithinForStmt() {
+        ForStmt forStmt = parse("for (int i=0, j=1;i<10;i++) { body(); }",
+                ParseStart.STATEMENT).asForStmt();
+        VariableDeclarationExpr initializations = forStmt.getInitialization().get(0).asVariableDeclarationExpr();
+        assertOneVarExposedToChildInContextNamed(initializations,
+                initializations.getVariable(1),
+                "i");
+        assertOneVarExposedToChildInContextNamed(forStmt,
+                forStmt.getCompare().get(),
+                "i");
+        assertOneVarExposedToChildInContextNamed(forStmt,
+                forStmt.getUpdate().get(0),
+                "i");
+        assertOneVarExposedToChildInContextNamed(forStmt,
+                forStmt.getBody(),
+                "i");
+    }
+
+    // The scope of a local variable declared in the FormalParameter part of an enhanced for statement (§14.14.2) is
+    // the contained Statement.
+
+    @Test
+    void localVariablesExposedToChildWithinEnhancedForeachStmt() {
+        ForEachStmt foreachStmt = parse("for (int i: myList) { body(); }",
+                ParseStart.STATEMENT).asForEachStmt();
+        assertOneVarExposedToChildInContextNamed(foreachStmt, foreachStmt.getBody(), "i");
+        assertNoVarsExposedToChildInContextNamed(foreachStmt, foreachStmt.getVariable(), "i");
+        assertNoVarsExposedToChildInContextNamed(foreachStmt, foreachStmt.getIterable(), "i");
+    }
+
+    // The scope of a parameter of an exception handler that is declared in a catch clause of a try statement (§14.20)
+    // is the entire block associated with the catch.
+
+    @Test
+    void parametersExposedToChildWithinTryStatement() {
+        CatchClause catchClause = parse("try {  } catch(Exception e) { body(); }",
+                ParseStart.STATEMENT).asTryStmt().getCatchClauses().get(0);
+        assertOneParamExposedToChildInContextNamed(catchClause, catchClause.getBody(), "e");
+        assertNoParamsExposedToChildInContextNamed(catchClause, catchClause.getParameter(), "e");
+    }
+
+    // The scope of a variable declared in the ResourceSpecification of a try-with-resources statement (§14.20.3) is
+    // from the declaration rightward over the remainder of the ResourceSpecification and the entire try block
+    // associated with the try-with-resources statement.
+
+    @Test
+    void localVariablesExposedToChildWithinTryWithResourcesStatement() {
+        TryStmt stmt = parse("try (Object res1 = foo(); Object res2 = foo()) { body(); }",
+                ParseStart.STATEMENT).asTryStmt();
+        assertOneVarExposedToChildInContextNamed(stmt, stmt.getResources().get(1), "res1");
+        assertNoVarsExposedToChildInContextNamed(stmt, stmt.getResources().get(0), "res1");
+        assertOneVarExposedToChildInContextNamed(stmt, stmt.getTryBlock(), "res1");
+    }
+
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/DefaultPackageTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/DefaultPackageTest.java
index 5fcead0..35e5a7c 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/DefaultPackageTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/DefaultPackageTest.java
@@ -1,6 +1,5 @@
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.JavaParser;
 import com.github.javaparser.ast.AccessSpecifier;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.resolution.UnsolvedSymbolException;
@@ -9,8 +8,9 @@
 import com.github.javaparser.resolution.types.ResolvedType;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -18,12 +18,14 @@
 import java.util.Optional;
 import java.util.Set;
 
-import static org.junit.Assert.assertEquals;
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 /**
  * See issue #16
  */
-public class DefaultPackageTest {
+class DefaultPackageTest {
 
     private class MyClassDeclaration extends AbstractClassDeclaration {
 
@@ -54,7 +56,7 @@
         }
 
         @Override
-        public List<ResolvedReferenceType> getAncestors() {
+        public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) {
             throw new UnsupportedOperationException();
         }
 
@@ -122,37 +124,46 @@
         public Optional<ResolvedReferenceTypeDeclaration> containerType() {
             throw new UnsupportedOperationException();
         }
+
+        @Override
+        public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {
+            throw new UnsupportedOperationException();
+        }
     }
 
     @Test
-    public void aClassInDefaultPackageCanBeAccessedFromTheDefaultPackage() {
+    void aClassInDefaultPackageCanBeAccessedFromTheDefaultPackage() {
         String code = "class A extends B {}";
         MemoryTypeSolver memoryTypeSolver = new MemoryTypeSolver();
         memoryTypeSolver.addDeclaration("B", new MyClassDeclaration("B"));
 
-        ClassOrInterfaceType jpType = JavaParser.parse(code).getClassByName("A").get().getExtendedTypes(0);
+        ClassOrInterfaceType jpType = parse(code).getClassByName("A").get().getExtendedTypes(0);
         ResolvedType resolvedType = JavaParserFacade.get(memoryTypeSolver).convertToUsage(jpType);
         assertEquals("B", resolvedType.asReferenceType().getQualifiedName());
     }
 
-    @Test(expected = UnsolvedSymbolException.class)
-    public void aClassInDefaultPackageCanBeAccessedFromOutsideTheDefaultPackageImportingIt() {
-        String code = "package myPackage; import B; class A extends B {}";
+    @Test
+    void aClassInDefaultPackageCanBeAccessedFromOutsideTheDefaultPackageImportingIt() {
+        assertThrows(UnsolvedSymbolException.class, () -> {
+            String code = "package myPackage; import B; class A extends B {}";
         MemoryTypeSolver memoryTypeSolver = new MemoryTypeSolver();
         memoryTypeSolver.addDeclaration("B", new MyClassDeclaration("B"));
-
-        ClassOrInterfaceType jpType = JavaParser.parse(code).getClassByName("A").get().getExtendedTypes(0);
+        ClassOrInterfaceType jpType = parse(code).getClassByName("A").get().getExtendedTypes(0);
         ResolvedType resolvedType = JavaParserFacade.get(memoryTypeSolver).convertToUsage(jpType);
         assertEquals("B", resolvedType.asReferenceType().getQualifiedName());
-    }
+    });
+                
+                }
 
-    @Test(expected = UnsolvedSymbolException.class)
-    public void aClassInDefaultPackageCanBeAccessedFromOutsideTheDefaultPackageWithoutImportingIt() {
-        String code = "package myPackage; class A extends B {}";
+    @Test
+    void aClassInDefaultPackageCanBeAccessedFromOutsideTheDefaultPackageWithoutImportingIt() {
+        assertThrows(UnsolvedSymbolException.class, () -> {
+            String code = "package myPackage; class A extends B {}";
         MemoryTypeSolver memoryTypeSolver = new MemoryTypeSolver();
         memoryTypeSolver.addDeclaration("B", new MyClassDeclaration("B"));
-
-        ResolvedType resolvedType = JavaParserFacade.get(memoryTypeSolver).convertToUsage(JavaParser.parse(code).getClassByName("A").get().getExtendedTypes(0));
+        ResolvedType resolvedType = JavaParserFacade.get(memoryTypeSolver).convertToUsage(parse(code).getClassByName("A").get().getExtendedTypes(0));
         assertEquals("B", resolvedType.asReferenceType().getQualifiedName());
-    }
+    });
+                
+        }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/EnumLiteralsInAnnotatedClassTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/EnumLiteralsInAnnotatedClassTest.java
new file mode 100644
index 0000000..6000834
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/EnumLiteralsInAnnotatedClassTest.java
@@ -0,0 +1,116 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StreamProvider;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class EnumLiteralsInAnnotatedClassTest {
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfClassUnqualifiedSamePackage() throws IOException {
+        File src = new File("src/test/resources/enumLiteralsInAnnotatedClass");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "AClass.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("BinaryExpr.Operator.OR") && n.getRange().get().begin.line == 4);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.BinaryExpr.Operator", fae.get().resolve().getType().describe());
+        assertEquals("OR", fae.get().resolve().getName());
+    }
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfClassQualifiedSamePackage() throws IOException {
+        File src = new File("src/test/resources/enumLiteralsInAnnotatedClass");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "AClass.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("foo.bar.BinaryExpr.Operator.AND") && n.getRange().get().begin.line == 5);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.BinaryExpr.Operator", fae.get().resolve().getType().describe());
+        assertEquals("AND", fae.get().resolve().getName());
+    }
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfClassUnqualifiedDifferentPackage() throws IOException {
+        File src = new File("src/test/resources/enumLiteralsInAnnotatedClass");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "differentpackage" + File.separator + "AClass2.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("BinaryExpr.Operator.OR") && n.getRange().get().begin.line == 6);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.BinaryExpr.Operator", fae.get().resolve().getType().describe());
+        assertEquals("OR", fae.get().resolve().getName());
+    }
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfClassQualifiedDifferentPackage() throws IOException {
+        File src = new File("src/test/resources/enumLiteralsInAnnotatedClass");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "differentpackage" + File.separator + "AClass2.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("foo.bar.BinaryExpr.Operator.AND") && n.getRange().get().begin.line == 7);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.BinaryExpr.Operator", fae.get().resolve().getType().describe());
+        assertEquals("AND", fae.get().resolve().getName());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/EnumResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/EnumResolutionTest.java
index edeaf80..448e881 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/EnumResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/EnumResolutionTest.java
@@ -16,32 +16,37 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
 import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.stmt.ReturnStmt;
 import com.github.javaparser.ast.stmt.SwitchStmt;
+import com.github.javaparser.resolution.declarations.ResolvedEnumConstantDeclaration;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class EnumResolutionTest extends AbstractResolutionTest {
+class EnumResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void switchOnEnum() {
+    void switchOnEnum() {
         CompilationUnit cu = parseSample("SwitchOnEnum");
-        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SwitchOnEnum");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SwitchOnEnum");
         MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
         SwitchStmt switchStmt = Navigator.findSwitch(method);
-        Expression expression = switchStmt.getEntries().get(0).getLabel().get();
+        Expression expression = switchStmt.getEntries().get(0).getLabels().get(0);
 
         SymbolReference<? extends ResolvedValueDeclaration> ref = JavaParserFacade.get(new ReflectionTypeSolver()).solve(expression);
         assertTrue(ref.isSolved());
@@ -49,13 +54,42 @@
     }
 
     @Test
-    public void enumAndStaticInitializer() {
+    void enumAndStaticInitializer() {
         CompilationUnit cu = parseSample("EnumAndStaticInitializer");
-        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MyClass");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MyClass");
         MethodCallExpr call = Navigator.findMethodCall(clazz, "put").get();
 
         ResolvedType ref = JavaParserFacade.get(new ReflectionTypeSolver()).getType(call);
         assertEquals("MyClass.Primitive", ref.describe());
     }
 
+    // Related to issue 1699
+    @Test
+    void resolveEnumConstantAccess() {
+        try {
+            // configure symbol solver before parsing
+            StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+            // parse compilation unit and get field access expression
+            CompilationUnit cu = parseSample("EnumFieldAccess");
+            ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "EnumFieldAccess");
+            MethodDeclaration method = Navigator.demandMethod(clazz, "accessField");
+            ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
+            FieldAccessExpr expression = returnStmt.getExpression().get().asFieldAccessExpr();
+
+            // resolve field access expression
+            ResolvedValueDeclaration resolvedValueDeclaration = expression.resolve();
+
+            assertFalse(resolvedValueDeclaration.isField());
+            assertTrue(resolvedValueDeclaration.isEnumConstant());
+
+            ResolvedEnumConstantDeclaration resolvedEnumConstantDeclaration = resolvedValueDeclaration.asEnumConstant();
+            assertEquals("SOME", resolvedEnumConstantDeclaration.getName());
+            assertTrue(resolvedEnumConstantDeclaration.isEnumConstant());
+            assertTrue(resolvedEnumConstantDeclaration.hasName());
+        } finally {
+            StaticJavaParser.setConfiguration(new ParserConfiguration());
+        }
+    }
+
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ExprResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ExprResolutionTest.java
new file mode 100644
index 0000000..7219585
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/ExprResolutionTest.java
@@ -0,0 +1,422 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.BinaryExpr;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+import static com.github.javaparser.resolution.types.ResolvedPrimitiveType.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ExprResolutionTest extends AbstractResolutionTest {
+
+    private TypeSolver ts;
+    private ResolvedType stringType;
+
+    @BeforeEach
+    void setup() {
+        ts = new ReflectionTypeSolver();
+        stringType = new ReferenceTypeImpl(ts.solveType(String.class.getCanonicalName()), ts);
+    }
+
+    // JLS 5.6.2. Binary Numeric Promotion
+    // Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the
+    // following rules:
+    //
+    // * If either operand is of type double, the other is converted to double.
+    // * Otherwise, if either operand is of type float, the other is converted to float.
+    // * Otherwise, if either operand is of type long, the other is converted to long.
+    // * Otherwise, both operands are converted to type int.
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsDoubleAndByte() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  byte b = (byte)0; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( d + b );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsByteAndDouble() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  byte b = (byte)0; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( b + d );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsDoubleAndChar() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  char c = 'a'; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( d + c );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsCharAndDouble() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  char c = 'a'; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( c + d );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsDoubleAndInt() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  int i = 0; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( d + i );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsIntAndDouble() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  int i = 0; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( i + d );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsfloatAndByte() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  byte b = (byte)0; "
+                        + "  float f = 0.0f; "
+                        + "  System.out.println( f + b );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(FLOAT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsByteAndfloat() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  byte b = (byte)0; "
+                        + "  float f = 0.0f; "
+                        + "  System.out.println( b + f );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(FLOAT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsfloatAndChar() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  char c = 'a'; "
+                        + "  float f = 0.0f; "
+                        + "  System.out.println( f + c );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(FLOAT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsCharAndfloat() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  char c = 'a'; "
+                        + "  float f = 0.0f; "
+                        + "  System.out.println( c + f );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(FLOAT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsfloatAndInt() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  int i = 0; "
+                        + "  float f = 0.0f; "
+                        + "  System.out.println( f + i );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(FLOAT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsIntAndfloat() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  int i = 0; "
+                        + "  float f = 0.0f; "
+                        + "  System.out.println( i + f );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(FLOAT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsDoubleAndFloat() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  float f = 0.0f; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( d + f );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsFloatAndDouble() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  float f = 0.0f; "
+                        + "  double d = 0.0; "
+                        + "  System.out.println( f + d );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(DOUBLE, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1589
+    @Test
+    void typeOfPlusExpressionsByteAndChar() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  byte b = (byte)0; "
+                        + "  char c = 'a'; "
+                        + "  System.out.println( b + c );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(INT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    @Test
+    void typeOfPlusExpressionsCharAndByte() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  byte b = (byte)0; "
+                        + "  char c = 'a'; "
+                        + "  System.out.println( c + b );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(INT, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1731
+    @Test
+    void typeOfPlusExpressionsDoubleAndString() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  String s1 = \"string1\";"
+                        + "  System.out.println( 1.0 + \"a_text\" );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(stringType, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1731
+    @Test
+    void typeOfPlusExpressionsIntAndString() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  String s1 = \"string1\";"
+                        + "  System.out.println( 1 + s1 );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(stringType, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1731
+    @Test
+    void typeOfPlusExpressionsCharAndString() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  String s1 = \"string1\";"
+                        + "  System.out.println( s1.charAt(2) + s1 );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(stringType, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1731
+    @Test
+    void typeOfPlusExpressionsStringAndDouble() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  String s1 = \"string1\";"
+                        + "  System.out.println( \"a_text\" + 1.0 );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(stringType, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1731
+    @Test
+    void typeOfPlusExpressionsStringAndInt() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  String s1 = \"string1\";"
+                        + "  System.out.println( s1 + 1 );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(stringType, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+    // Related to issue 1731
+    @Test
+    void typeOfPlusExpressionsStringAndChar() {
+        CompilationUnit compilationUnit = parse(
+                "public class Class1 {"
+                        + " public void method1() {"
+                        + "  String s1 = \"string1\";"
+                        + "  System.out.println( s1 + s1.charAt(2) );"
+                        + " }"
+                        + "}");
+
+        List<BinaryExpr> bExprs = compilationUnit.findAll(BinaryExpr.class);
+        assertEquals(1, bExprs.size());
+        assertEquals(stringType, JavaParserFacade.get(ts).getType(bExprs.get(0)));
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/FieldsResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/FieldsResolutionTest.java
index fd95e73..211ebef 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/FieldsResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/FieldsResolutionTest.java
@@ -16,33 +16,46 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
 import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.stmt.ExpressionStmt;
 import com.github.javaparser.ast.stmt.ReturnStmt;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class FieldsResolutionTest extends AbstractResolutionTest {
+class FieldsResolutionTest extends AbstractResolutionTest {
+
+    @AfterEach
+    void resetConfiguration() {
+        StaticJavaParser.setConfiguration(new ParserConfiguration());
+    }
 
     @Test
-    public void accessClassFieldThroughThis() {
+    void accessClassFieldThroughThis() {
         CompilationUnit cu = parseSample("AccessClassMemberThroughThis");
-        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessClassMemberThroughThis");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessClassMemberThroughThis");
         MethodDeclaration method = Navigator.demandMethod(clazz, "getLabel2");
         ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
         Expression expression = returnStmt.getExpression().get();
@@ -52,16 +65,16 @@
     }
 
     @Test
-    public void accessClassFieldThroughThisWithCompetingSymbolInParentContext() {
+    void accessClassFieldThroughThisWithCompetingSymbolInParentContext() {
         CompilationUnit cu = parseSample("AccessClassMemberThroughThis");
-        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessClassMemberThroughThis");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessClassMemberThroughThis");
         MethodDeclaration method = Navigator.demandMethod(clazz, "setLabel");
         ExpressionStmt expressionStmt = (ExpressionStmt) method.getBody().get().getStatements().get(0);
         AssignExpr assignExpr = (AssignExpr) expressionStmt.getExpression();
         FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) assignExpr.getTarget();
 
-        File src = adaptPath(new File("src/test/resources"));
-        CombinedTypeSolver typeSolver = new CombinedTypeSolver(new JavaParserTypeSolver(src), new ReflectionTypeSolver());
+        Path src = adaptPath("src/test/resources");
+        CombinedTypeSolver typeSolver = new CombinedTypeSolver(new JavaParserTypeSolver(src, new LeanParserConfiguration()), new ReflectionTypeSolver());
         SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
         SymbolReference<? extends ResolvedValueDeclaration> ref = symbolSolver.solveSymbol(fieldAccessExpr.getName().getId(), fieldAccessExpr);
 
@@ -70,9 +83,9 @@
     }
 
     @Test
-    public void accessEnumFieldThroughThis() {
+    void accessEnumFieldThroughThis() {
         CompilationUnit cu = parseSample("AccessEnumMemberThroughThis");
-        com.github.javaparser.ast.body.EnumDeclaration enumDecl = Navigator.demandEnum(cu, "AccessEnumMemberThroughThis");
+        EnumDeclaration enumDecl = Navigator.demandEnum(cu, "AccessEnumMemberThroughThis");
         MethodDeclaration method = Navigator.demandMethod(enumDecl, "getLabel");
         SimpleName expression = Navigator.findSimpleName(method, "label").get();
 
@@ -82,9 +95,9 @@
     }
 
     @Test
-    public void accessEnumMethodThroughThis() {
+    void accessEnumMethodThroughThis() {
         CompilationUnit cu = parseSample("AccessEnumMemberThroughThis");
-        com.github.javaparser.ast.body.EnumDeclaration enumDecl = Navigator.demandEnum(cu, "AccessEnumMemberThroughThis");
+        EnumDeclaration enumDecl = Navigator.demandEnum(cu, "AccessEnumMemberThroughThis");
         MethodDeclaration method = Navigator.demandMethod(enumDecl, "getLabel2");
         ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
         Expression expression = returnStmt.getExpression().get();
@@ -94,9 +107,9 @@
     }
 
     @Test
-    public void accessFieldThroughSuper() {
+    void accessClassFieldThroughSuper() {
         CompilationUnit cu = parseSample("AccessThroughSuper");
-        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessThroughSuper.SubClass");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessThroughSuper.SubClass");
         MethodDeclaration method = Navigator.demandMethod(clazz, "fieldTest");
         ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
         Expression expression = returnStmt.getExpression().get();
@@ -104,4 +117,109 @@
         ResolvedType ref = JavaParserFacade.get(new ReflectionTypeSolver()).getType(expression);
         assertEquals("java.lang.String", ref.describe());
     }
+
+    @Test
+    void resolveClassFieldThroughThis() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get field access expression
+        CompilationUnit cu = parseSample("AccessClassMemberThroughThis");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessClassMemberThroughThis");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "getLabel2");
+        ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
+        FieldAccessExpr expression = returnStmt.getExpression().get().asFieldAccessExpr();
+
+        // resolve field access expression
+        ResolvedValueDeclaration resolvedValueDeclaration = expression.resolve();
+
+        // get expected field declaration
+        VariableDeclarator variableDeclarator = Navigator.demandField(clazz, "label");
+
+        // check that the expected field declaration equals the resolved field declaration
+        assertEquals(variableDeclarator, ((JavaParserFieldDeclaration) resolvedValueDeclaration).getVariableDeclarator());
+    }
+
+    @Test
+    void resolveClassFieldThroughSuper() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get field access expression
+        CompilationUnit cu = parseSample("AccessThroughSuper");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessThroughSuper.SubClass");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "fieldTest");
+        ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
+        FieldAccessExpr expression = returnStmt.getExpression().get().asFieldAccessExpr();
+
+        // resolve field access expression
+        ResolvedValueDeclaration resolvedValueDeclaration = expression.resolve();
+
+        // get expected field declaration
+        clazz = Navigator.demandClass(cu, "AccessThroughSuper.SuperClass");
+        VariableDeclarator variableDeclarator = Navigator.demandField(clazz, "field");
+
+        // check that the expected field declaration equals the resolved field declaration
+        assertEquals(variableDeclarator, ((JavaParserFieldDeclaration) resolvedValueDeclaration).getVariableDeclarator());
+    }
+
+    @Test
+    void resolveClassFieldOfClassExtendingUnknownClass1() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get field access expression
+        CompilationUnit cu = parseSample("ClassExtendingUnknownClass");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassExtendingUnknownClass");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "getFoo");
+        ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
+        NameExpr expression = returnStmt.getExpression().get().asNameExpr();
+
+        // resolve field access expression
+        ResolvedValueDeclaration resolvedValueDeclaration = expression.resolve();
+
+        // get expected field declaration
+        VariableDeclarator variableDeclarator = Navigator.demandField(clazz, "foo");
+
+        // check that the expected field declaration equals the resolved field declaration
+        assertEquals(variableDeclarator, ((JavaParserFieldDeclaration) resolvedValueDeclaration).getVariableDeclarator());
+    }
+
+    @Test
+    void resolveClassFieldOfClassExtendingUnknownClass2() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get field access expression
+        CompilationUnit cu = parseSample("ClassExtendingUnknownClass");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassExtendingUnknownClass");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "getFoo2");
+        ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
+        FieldAccessExpr expression = returnStmt.getExpression().get().asFieldAccessExpr();
+
+        // resolve field access expression
+        ResolvedValueDeclaration resolvedValueDeclaration = expression.resolve();
+
+        // get expected field declaration
+        VariableDeclarator variableDeclarator = Navigator.demandField(clazz, "foo");
+
+        // check that the expected field declaration equals the resolved field declaration
+        assertEquals(variableDeclarator, ((JavaParserFieldDeclaration) resolvedValueDeclaration).getVariableDeclarator());
+    }
+
+    @Test
+    void resolveInheritedFieldFromInterface() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get field access expression
+        CompilationUnit cu = parseSample("ReflectionTypeSolverFieldFromInterfaceResolution");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Test");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
+        ReturnStmt returnStmt = (ReturnStmt) method.getBody().get().getStatements().get(0);
+        Expression expression = returnStmt.getExpression().get();
+
+        ResolvedType ref = JavaParserFacade.get(new ReflectionTypeSolver()).getType(expression);
+        assertEquals("int", ref.describe());
+    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/GenericsResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/GenericsResolutionTest.java
index bfc4bfd..deeeee1 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/GenericsResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/GenericsResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
@@ -35,17 +34,20 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.model.resolution.Value;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.List;
 import java.util.Optional;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class GenericsResolutionTest extends AbstractResolutionTest {
+/**
+ * Tests related to resolved Generics types.
+ */
+class GenericsResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void resolveFieldWithGenericTypeToString() {
+    void resolveFieldWithGenericTypeToString() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Generics");
         VariableDeclarator fieldS = Navigator.demandField(clazz, "s");
@@ -62,7 +64,7 @@
     }
 
     @Test
-    public void resolveFieldWithGenericTypeToDeclaredClass() {
+    void resolveFieldWithGenericTypeToDeclaredClass() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Generics");
         VariableDeclarator fieldS = Navigator.demandField(clazz, "g");
@@ -79,7 +81,7 @@
     }
 
     @Test
-    public void resolveFieldWithGenericTypeToInteger() {
+    void resolveFieldWithGenericTypeToInteger() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Generics");
         VariableDeclarator fieldS = Navigator.demandField(clazz, "i");
@@ -96,7 +98,7 @@
     }
 
     @Test
-    public void resolveFieldOfVariableType() {
+    void resolveFieldOfVariableType() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
         VariableDeclarator field = Navigator.demandField(clazz, "a");
@@ -113,7 +115,7 @@
     }
 
     @Test
-    public void resolveFieldOfGenericReferringToVariableType() {
+    void resolveFieldOfGenericReferringToVariableType() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
         VariableDeclarator field = Navigator.demandField(clazz, "as");
@@ -134,7 +136,7 @@
     }
 
     @Test
-    public void resolveUsageOfGenericFieldSimpleCase() {
+    void resolveUsageOfGenericFieldSimpleCase() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
 
@@ -150,7 +152,7 @@
 
     //PRIMA UN TEST CHE DICA CHE IL TIPO DEL CAMPO AS e' LIST<A> NON LIST<E>
     @Test
-    public void resolveUsageOfGenericFieldIntermediateCase() {
+    void resolveUsageOfGenericFieldIntermediateCase() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
 
@@ -166,7 +168,7 @@
     }
 
     @Test
-    public void resolveUsageOfGenericFieldAdvancedCase() {
+    void resolveUsageOfGenericFieldAdvancedCase() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
 
@@ -184,7 +186,7 @@
     }
 
     @Test
-    public void resolveUsageOfMethodOfGenericClass() {
+    void resolveUsageOfMethodOfGenericClass() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericMethodCalls.Derived");
         MethodDeclaration method = Navigator.demandMethod(clazz, "caller");
@@ -196,7 +198,33 @@
     }
 
     @Test
-    public void resolveElementOfList() {
+    void resolveUsageOfMethodOfGenericClassWithUnboundedWildcard() {
+        CompilationUnit cu = parseSample("GenericsWildcard");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericsWildcard");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "unbounded");
+        MethodCallExpr expression = Navigator.findMethodCall(method, "toString").get();
+
+        MethodUsage methodUsage = JavaParserFacade.get(new ReflectionTypeSolver()).solveMethodAsUsage(expression);
+
+        assertEquals("toString", methodUsage.getName());
+        assertEquals("java.lang.Object", methodUsage.declaringType().getQualifiedName());
+    }
+
+    @Test
+    void resolveUsageOfMethodOfGenericClassWithExtendsWildcard() {
+        CompilationUnit cu = parseSample("GenericsWildcard");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "GenericsWildcard");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "bounded");
+        MethodCallExpr expression = Navigator.findMethodCall(method, "bar").get();
+
+        MethodUsage methodUsage = JavaParserFacade.get(new ReflectionTypeSolver()).solveMethodAsUsage(expression);
+
+        assertEquals("bar", methodUsage.getName());
+        assertEquals("GenericsWildcard.Foo", methodUsage.declaringType().getQualifiedName());
+    }
+
+    @Test
+    void resolveElementOfList() {
         CompilationUnit cu = parseSample("ElementOfList");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ElementOfList");
         MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
@@ -210,7 +238,7 @@
     }
 
     @Test
-    public void resolveElementOfListAdvancedExample() {
+    void resolveElementOfListAdvancedExample() {
         CompilationUnit cu = parseSample("ElementOfList");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ElementOfList");
         MethodDeclaration method = Navigator.demandMethod(clazz, "annotations");
@@ -224,7 +252,7 @@
     }
 
     @Test
-    public void genericsInheritance() {
+    void genericsInheritance() {
         CompilationUnit cu = parseSample("MethodTypeParams");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "VoidVisitorAdapter");
         MethodDeclaration method = Navigator.demandMethod(clazz, "visit");
@@ -240,7 +268,7 @@
     }
 
     @Test
-    public void methodTypeParams() {
+    void methodTypeParams() {
         CompilationUnit cu = parseSample("MethodTypeParams");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "VoidVisitorAdapter");
         MethodDeclaration method = Navigator.demandMethod(clazz, "visit");
@@ -253,7 +281,7 @@
     }
 
     @Test
-    public void classCastScope() {
+    void classCastScope() {
         CompilationUnit cu = parseSample("ClassCast");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassCast");
         MethodDeclaration method = Navigator.demandMethod(clazz, "getNodesByType");
@@ -270,7 +298,7 @@
     }
 
     @Test
-    public void classCast() {
+    void classCast() {
         CompilationUnit cu = parseSample("ClassCast");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassCast");
         MethodDeclaration method = Navigator.demandMethod(clazz, "getNodesByType");
@@ -283,7 +311,7 @@
     }
 
     @Test
-    public void typeParamOnReturnTypeStep1() {
+    void typeParamOnReturnTypeStep1() {
         CompilationUnit cu = parseSample("TypeParamOnReturnType");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
         MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
@@ -296,7 +324,7 @@
     }
 
     @Test
-    public void typeParamOnReturnTypeStep2() {
+    void typeParamOnReturnTypeStep2() {
         CompilationUnit cu = parseSample("TypeParamOnReturnType");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
         MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
@@ -309,7 +337,7 @@
     }
 
     @Test
-    public void typeParamOnReturnTypeStep3() {
+    void typeParamOnReturnTypeStep3() {
         CompilationUnit cu = parseSample("TypeParamOnReturnType");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
         MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
@@ -323,7 +351,7 @@
     }
 
     @Test
-    public void typeParamOnReturnType() {
+    void typeParamOnReturnType() {
         CompilationUnit cu = parseSample("TypeParamOnReturnType");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypeParamOnReturnType");
         MethodDeclaration method = Navigator.demandMethod(clazz, "nodeEquals");
@@ -390,7 +418,7 @@
     }*/
 
     @Test
-    public void genericCollectionWithWildcardsAndExtensions() {
+    void genericCollectionWithWildcardsAndExtensions() {
         CompilationUnit cu = parseSample("GenericCollectionWithExtension");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
         MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
@@ -407,7 +435,7 @@
     }
 
     @Test
-    public void methodWithGenericParameterTypes() {
+    void methodWithGenericParameterTypes() {
         CompilationUnit cu = parseSample("GenericCollectionWithExtension");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
         MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
@@ -422,7 +450,7 @@
     }
 
     @Test
-    public void genericCollectionWithWildcards() {
+    void genericCollectionWithWildcards() {
         CompilationUnit cu = parseSample("GenericCollection");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Foo");
         MethodDeclaration method = Navigator.demandMethod(clazz, "bar");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/InternalClassInInterfaceTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/InternalClassInInterfaceTest.java
new file mode 100644
index 0000000..d692552
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/InternalClassInInterfaceTest.java
@@ -0,0 +1,117 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StreamProvider;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class InternalClassInInterfaceTest {
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfInterfaceUnqualifiedSamePackage() throws IOException {
+        File src = new File("src/test/resources/internalClassInInterface");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "AClass.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("AnInterface.ListChangeType.ADDITION") && n.getRange().get().begin.line == 4);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.AnInterface.ListChangeType", fae.get().resolve().getType().describe());
+        assertEquals("ADDITION", fae.get().resolve().getName());
+    }
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfInterfaceQualifiedSamePackage() throws IOException {
+        File src = new File("src/test/resources/internalClassInInterface");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "AClass.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("foo.bar.AnInterface.ListChangeType.ADDITION") && n.getRange().get().begin.line == 5);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.AnInterface.ListChangeType", fae.get().resolve().getType().describe());
+        assertEquals("ADDITION", fae.get().resolve().getName());
+    }
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfInterfaceUnqualifiedDifferentPackage() throws IOException {
+        File src = new File("src/test/resources/internalClassInInterface");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "differentpackage" + File.separator + "AClass2.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("AnInterface.ListChangeType.ADDITION") && n.getRange().get().begin.line == 6);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.AnInterface.ListChangeType", fae.get().resolve().getType().describe());
+        assertEquals("ADDITION", fae.get().resolve().getName());
+    }
+
+    @Test
+    void resolveFieldOfEnumAsInternalClassOfInterfaceQualifiedDifferentPackage() throws IOException {
+        File src = new File("src/test/resources/internalClassInInterface");
+        File aClass = new File(src.getPath() + File.separator + "foo" + File.separator + "bar"
+                + File.separator + "differentpackage" + File.separator + "AClass2.java");
+
+        CombinedTypeSolver localCts = new CombinedTypeSolver();
+        localCts.add(new ReflectionTypeSolver());
+        localCts.add(new JavaParserTypeSolver(src));
+
+        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(localCts));
+        JavaParser parser = new JavaParser(parserConfiguration);
+        StreamProvider classProvider = new StreamProvider(new FileInputStream(aClass));
+
+        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, classProvider).getResult().get();
+
+        Optional<FieldAccessExpr> fae = cu.findFirst(FieldAccessExpr.class, n -> n.toString().equals("foo.bar.AnInterface.ListChangeType.ADDITION") && n.getRange().get().begin.line == 7);
+
+        assertTrue(fae.isPresent());
+
+        assertEquals("foo.bar.AnInterface.ListChangeType", fae.get().resolve().getType().describe());
+        assertEquals("ADDITION", fae.get().resolve().getName());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java
index 37fec26..99592b3 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/JavaParserFacadeResolutionTest.java
@@ -24,7 +24,6 @@
 import com.github.javaparser.ast.expr.MethodCallExpr;
 import com.github.javaparser.ast.expr.NameExpr;
 import com.github.javaparser.ast.stmt.CatchClause;
-import com.github.javaparser.ast.stmt.TryStmt;
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
@@ -38,15 +37,18 @@
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static com.github.javaparser.StaticJavaParser.parse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 
-public class JavaParserFacadeResolutionTest extends AbstractResolutionTest {
+class JavaParserFacadeResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void typeDeclarationSuperClassImplicitlyIncludeObject() {
+    void typeDeclarationSuperClassImplicitlyIncludeObject() {
         CompilationUnit cu = parseSample("Generics");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Generics");
         ResolvedTypeDeclaration typeDeclaration = JavaParserFacade.get(new ReflectionTypeSolver()).getTypeDeclaration(clazz);
@@ -56,7 +58,7 @@
 
     // See issue 42
     @Test
-    public void solvingReferenceToUnsupportedOperationException() {
+    void solvingReferenceToUnsupportedOperationException() {
         String code = "public class Bla {\n" +
                 "    public void main()\n" +
                 "    {\n" +
@@ -71,14 +73,14 @@
                 "        }\n" +
                 "    }\n" +
                 "}";
-        MethodCallExpr methodCallExpr = Navigator.findNodeOfGivenClass(JavaParser.parse(code), MethodCallExpr.class);
+        MethodCallExpr methodCallExpr = Navigator.findNodeOfGivenClass(parse(code), MethodCallExpr.class);
         MethodUsage methodUsage = JavaParserFacade.get(new ReflectionTypeSolver()).solveMethodAsUsage(methodCallExpr);
         assertEquals("java.lang.Throwable.getMessage()", methodUsage.getQualifiedSignature());
     }
 
     // See issue 46
     @Test
-    public void solvingReferenceToCatchClauseParam() {
+    void solvingReferenceToCatchClauseParam() {
         String code = "public class Bla {\n" +
                 "    public void main()\n" +
                 "    {\n" +
@@ -93,18 +95,18 @@
                 "        }\n" +
                 "    }\n" +
                 "}";
-        MethodCallExpr methodCallExpr = Navigator.findNodeOfGivenClass(JavaParser.parse(code), MethodCallExpr.class);
-        NameExpr nameE = (NameExpr)methodCallExpr.getScope().get();
+        MethodCallExpr methodCallExpr = Navigator.findNodeOfGivenClass(parse(code), MethodCallExpr.class);
+        NameExpr nameE = (NameExpr) methodCallExpr.getScope().get();
         SymbolReference<? extends ResolvedValueDeclaration> symbolReference = JavaParserFacade.get(new ReflectionTypeSolver()).solve(nameE);
-        assertEquals(true, symbolReference.isSolved());
-        assertEquals(true, symbolReference.getCorrespondingDeclaration().isParameter());
+        assertTrue(symbolReference.isSolved());
+        assertTrue(symbolReference.getCorrespondingDeclaration().isParameter());
         assertEquals("e", symbolReference.getCorrespondingDeclaration().asParameter().getName());
         assertEquals("java.lang.UnsupportedOperationException", symbolReference.getCorrespondingDeclaration().asParameter().getType().asReferenceType().getQualifiedName());
     }
 
     // See issue 47
     @Test
-    public void solvingReferenceToAnAncestorInternalClass() {
+    void solvingReferenceToAnAncestorInternalClass() {
         String code = "public class Foo {\n" +
                 "    public class Base {\n" +
                 "        public class X {\n" +
@@ -115,7 +117,7 @@
                 "        public X x = null;\n" +
                 "    }\n" +
                 "}";
-        FieldDeclaration fieldDeclaration = Navigator.findNodeOfGivenClass(JavaParser.parse(code), FieldDeclaration.class);
+        FieldDeclaration fieldDeclaration = Navigator.findNodeOfGivenClass(parse(code), FieldDeclaration.class);
         Type jpType = fieldDeclaration.getCommonType();
         ResolvedType jssType = JavaParserFacade.get(new ReflectionTypeSolver()).convertToUsage(jpType);
         assertEquals("Foo.Base.X", jssType.asReferenceType().getQualifiedName());
@@ -123,15 +125,15 @@
 
     // See issue 119
     @Test
-    public void solveTryWithResourceVariable() {
+    void solveTryWithResourceVariable() {
         String code = "import java.util.Scanner; class A { void foo() { try (Scanner sc = new Scanner(System.in)) {\n" +
                 "    sc.nextLine();\n" +
                 "} } }";
-        CompilationUnit cu = JavaParser.parse(code);
+        CompilationUnit cu = parse(code);
         MethodCallExpr methodCallExpr = Navigator.findMethodCall(cu, "nextLine").get();
         Expression scope = methodCallExpr.getScope().get();
         ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver()).getType(scope);
-        assertEquals(true, type.isReferenceType());
+        assertTrue(type.isReferenceType());
         assertEquals("java.util.Scanner", type.asReferenceType().getQualifiedName());
     }
 
@@ -144,7 +146,7 @@
     }
 
     @Test
-    public void solveMultiCatchType() {
+    void solveMultiCatchType() {
         String code = "class A {\n" +
                 "        public void foo() {\n" +
                 "            try {\n" +
@@ -158,6 +160,18 @@
         CatchClause catchClause = Navigator.findNodeOfGivenClass(cu, CatchClause.class);
         Type jpType = catchClause.getParameter().getType();
         ResolvedType jssType = jpType.resolve();
-        assertEquals(true, jssType instanceof ResolvedUnionType);
+        assertTrue(jssType instanceof ResolvedUnionType);
+    }
+
+    @Test
+    void classToResolvedTypeViaReflection() {
+        Class<?> clazz = this.getClass();
+        ReflectionTypeSolver reflectionTypeSolver = new ReflectionTypeSolver();
+        JavaParserFacade facade = JavaParserFacade.get(reflectionTypeSolver);
+        ResolvedType resolvedType = facade.classToResolvedType(clazz);
+
+        assertNotNull(resolvedType);
+        assertTrue(resolvedType.isReferenceType());
+        assertEquals(clazz.getCanonicalName(), resolvedType.asReferenceType().getQualifiedName());
     }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/LambdaResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/LambdaResolutionTest.java
index 3620c52..afb2320 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/LambdaResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/LambdaResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.Expression;
@@ -27,14 +26,14 @@
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class LambdaResolutionTest extends AbstractResolutionTest {
+class LambdaResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void lambdaMapParameter() {
+    void lambdaMapParameter() {
         CompilationUnit cu = parseSample("Lambda");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "lambdaMap");
@@ -48,7 +47,7 @@
     }
 
     @Test
-    public void personsStream() {
+    void personsStream() {
         CompilationUnit cu = parseSample("Lambda");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "lambdaMap");
@@ -62,7 +61,7 @@
     }
 
     @Test
-    public void lambdaMap() {
+    void lambdaMap() {
         CompilationUnit cu = parseSample("Lambda");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration m1 = Navigator.demandMethod(clazz, "lambdaMap");
@@ -80,7 +79,7 @@
     }
 
     @Test
-    public void lambdaReduce() {
+    void lambdaReduce() {
         CompilationUnit cu = parseSample("Lambda");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "reduce");
@@ -93,7 +92,20 @@
     }
 
     @Test
-    public void lambdaBifunc() {
+    void lambdaPrint() {
+        CompilationUnit cu = parseSample("Lambda");
+        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "print");
+        ReturnStmt returnStmt = Navigator.findReturnStmt(method);
+        Expression expr = returnStmt.getExpression().get();
+
+        JavaParserFacade javaParserFacade = JavaParserFacade.get(new ReflectionTypeSolver());
+        ResolvedType type1 = javaParserFacade.getType(expr);
+        assertEquals("void", type1.describe());
+    }
+
+    @Test
+    void lambdaBifunc() {
         CompilationUnit cu = parseSample("Lambda");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "bifunc");
@@ -106,7 +118,7 @@
     }
 
     @Test
-    public void lambdaCollectParam() {
+    void lambdaCollectParam() {
         CompilationUnit cu = parseSample("LambdaCollect");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "lambdaMap");
@@ -121,7 +133,7 @@
     }
 
     @Test
-    public void lambdaCollect() {
+    void lambdaCollect() {
         CompilationUnit cu = parseSample("LambdaCollect");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "lambdaMap");
@@ -134,7 +146,7 @@
     }
 
     @Test
-    public void lambdaBlockExplicitReturn() {
+    void lambdaBlockExplicitReturn() {
         CompilationUnit cu = parseSample("LambdaMulti");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "lambdaSingleReturn");
@@ -147,7 +159,7 @@
     }
 
     @Test
-    public void lambdaBlockMultiLineReturn() {
+    void lambdaBlockMultiLineReturn() {
         CompilationUnit cu = parseSample("LambdaMulti");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "multiLineReturn");
@@ -160,7 +172,7 @@
     }
 
     @Test
-    public void typeOfVoidLambda() {
+    void typeOfVoidLambda() {
         CompilationUnit cu = parseSample("LambdaVoid");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         MethodDeclaration method = Navigator.demandMethod(clazz, "lambdaEmpty");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodLikeSignaturesTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodLikeSignaturesTest.java
new file mode 100644
index 0000000..cf5eeb6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodLikeSignaturesTest.java
@@ -0,0 +1,51 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.resolution.declarations.ResolvedConstructorDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MethodLikeSignaturesTest extends AbstractResolutionTest {
+
+    @Test
+    void checkReflectionConstructorSignature() {
+        CompilationUnit cu = parseSample("MethodLikeSignaturesTest");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodLikeSignaturesTest");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
+        ObjectCreationExpr objectCreationExpr = method.getBody().get().getStatements().get(0)
+                                                        .asExpressionStmt().getExpression().asVariableDeclarationExpr()
+                                                        .getVariable(0).getInitializer().get().asObjectCreationExpr();
+
+        ResolvedConstructorDeclaration resolvedConstructorDeclaration =
+                JavaParserFacade.get(new ReflectionTypeSolver()).solve(objectCreationExpr).getCorrespondingDeclaration();
+
+        assertEquals("File", resolvedConstructorDeclaration.getName());
+        assertEquals("File(java.lang.String)", resolvedConstructorDeclaration.getSignature());
+        assertEquals("java.io.File.File(java.lang.String)", resolvedConstructorDeclaration.getQualifiedSignature());
+    }
+
+    @Test
+    void checkReflectionMethodSignature() {
+        CompilationUnit cu = parseSample("MethodLikeSignaturesTest");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodLikeSignaturesTest");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
+        MethodCallExpr methodCallExpr = method.getBody().get().getStatements().get(1)
+                                                .asExpressionStmt().getExpression().asMethodCallExpr();
+
+        ResolvedMethodDeclaration resolvedMethodDeclaration =
+                JavaParserFacade.get(new ReflectionTypeSolver()).solve(methodCallExpr).getCorrespondingDeclaration();
+
+        assertEquals("delete", resolvedMethodDeclaration.getName());
+        assertEquals("delete()", resolvedMethodDeclaration.getSignature());
+        assertEquals("java.io.File.delete()", resolvedMethodDeclaration.getQualifiedSignature());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionLogicTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionLogicTest.java
index b53607d..1c8cbeb 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionLogicTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionLogicTest.java
@@ -24,30 +24,31 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class MethodsResolutionLogicTest extends AbstractResolutionTest {
+class MethodsResolutionLogicTest extends AbstractResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
-        File srcNewCode = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
+    @BeforeEach
+    void setup() {
+        Path srcNewCode = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
         CombinedTypeSolver combinedTypeSolverNewCode = new CombinedTypeSolver();
         combinedTypeSolverNewCode.add(new ReflectionTypeSolver());
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(srcNewCode));
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
+        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(srcNewCode, new LeanParserConfiguration()));
+        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"), new LeanParserConfiguration()));
         typeSolver = combinedTypeSolverNewCode;
     }
 
     @Test
-    public void compatibilityShouldConsiderAlsoTypeVariablesNegative() {
+    void compatibilityShouldConsiderAlsoTypeVariablesNegative() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         ResolvedReferenceType stringType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(String.class, typeSolver);
@@ -60,7 +61,7 @@
     }
 
     @Test
-    public void compatibilityShouldConsiderAlsoTypeVariablesRaw() {
+    void compatibilityShouldConsiderAlsoTypeVariablesRaw() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         ResolvedReferenceType rawClassType = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(Class.class, typeSolver);
@@ -70,7 +71,7 @@
     }
 
     @Test
-    public void compatibilityShouldConsiderAlsoTypeVariablesPositive() {
+    void compatibilityShouldConsiderAlsoTypeVariablesPositive() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolver.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         ResolvedReferenceType runtimeException = (ResolvedReferenceType) ReflectionFactory.typeUsageFor(RuntimeException.class, typeSolver);
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionTest.java
index 2e6dc94..d6efa26 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionTest.java
@@ -16,30 +16,94 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.expr.MethodCallExpr;
 import com.github.javaparser.ast.expr.ThisExpr;
-import com.github.javaparser.ast.stmt.ReturnStmt;
+import com.github.javaparser.ast.stmt.*;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import com.github.javaparser.utils.Log;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class MethodsResolutionTest extends AbstractResolutionTest {
+class MethodsResolutionTest extends AbstractResolutionTest {
+
+    @AfterEach
+    void resetConfiguration() {
+        StaticJavaParser.setConfiguration(new ParserConfiguration());
+        Log.setAdapter(new Log.SilentAdapter());
+    }
 
     @Test
-    public void solveMethodAccessThroughSuper() {
+    void testConsistentMethodResultion() {
+        Log.setAdapter(new Log.StandardOutStandardErrorAdapter());
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        CompilationUnit cu = parseSample("PlatformTestUtil");
+        ClassOrInterfaceDeclaration classDeclaration = Navigator.demandClass(cu, "PlatformTestUtil");
+        MethodDeclaration methodDeclaration =
+                Navigator.demandMethod(classDeclaration, "assertComparisonContractNotViolated");
+
+        ForStmt outerFor = (ForStmt) methodDeclaration.getBody().get().getStatement(0);
+        ForStmt innerFor = (ForStmt) ((BlockStmt) outerFor.getBody()).getStatement(0);
+        IfStmt ifStmt = (IfStmt) ((BlockStmt) innerFor.getBody()).getStatement(4);
+        MethodCallExpr assertCall = (MethodCallExpr) ((ExpressionStmt) ((BlockStmt) ifStmt.getThenStmt()).getStatement(0)).getExpression();
+        MethodCallExpr formatCall = (MethodCallExpr) assertCall.getArguments().get(0);
+
+        boolean exception1, exception2, exception3, exception4;
+        try {
+            formatCall.resolve();
+            exception1 = false;
+        } catch (Exception e) {
+            exception1 = true;
+        }
+
+        try {
+            formatCall.resolve();
+            exception2 = false;
+        } catch (Exception e) {
+            exception2 = true;
+        }
+
+        try {
+            formatCall.resolve();
+            exception3 = false;
+        } catch (Exception e) {
+            exception3 = true;
+        }
+
+        try {
+            formatCall.resolve();
+            exception4 = false;
+        } catch (Exception e) {
+            exception4 = true;
+        }
+
+        assertEquals(exception1, exception2);
+        assertEquals(exception1, exception3);
+        assertEquals(exception1, exception4);
+    }
+
+    @Test
+    void solveMethodAccessThroughSuper() {
         CompilationUnit cu = parseSample("AccessThroughSuper");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "AccessThroughSuper.SubClass");
         MethodDeclaration method = Navigator.demandMethod(clazz, "methodTest");
@@ -51,7 +115,7 @@
     }
 
     @Test
-    public void solveMethodWithClassExpressionAsParameter() {
+    void solveMethodWithClassExpressionAsParameter() {
         CompilationUnit cu = parseSample("ClassExpression");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassExpression");
         MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
@@ -62,7 +126,7 @@
     }
 
     @Test
-    public void solveMethodInInterfaceParent() {
+    void solveMethodInInterfaceParent() {
         CompilationUnit cu = parseSample("MethodCalls");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
 
@@ -77,7 +141,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToLong() {
+    void solveMethodWithTypePromotionsToLong() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotions");
 
@@ -111,7 +175,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToInt() {
+    void solveMethodWithTypePromotionsToInt() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotions");
 
@@ -144,7 +208,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToShort() {
+    void solveMethodWithTypePromotionsToShort() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotions");
 
@@ -176,7 +240,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToByte() {
+    void solveMethodWithTypePromotionsToByte() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotions");
 
@@ -207,7 +271,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToLongWithExtraParam() {
+    void solveMethodWithTypePromotionsToLongWithExtraParam() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotionsWithExtraParam");
 
@@ -241,7 +305,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToIntWithExtraParam() {
+    void solveMethodWithTypePromotionsToIntWithExtraParam() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotionsWithExtraParam");
 
@@ -274,7 +338,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToShortWithExtraParam() {
+    void solveMethodWithTypePromotionsToShortWithExtraParam() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotionsWithExtraParam");
 
@@ -306,7 +370,7 @@
     }
 
     @Test
-    public void solveMethodWithTypePromotionsToByteWithExtraParam() {
+    void solveMethodWithTypePromotionsToByteWithExtraParam() {
         CompilationUnit cu = parseSample("Issue338");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TypePromotionsWithExtraParam");
 
@@ -337,7 +401,7 @@
     }
 
     @Test
-    public void callOnThisInAnonymousClass() {
+    void callOnThisInAnonymousClass() {
         CompilationUnit cu = parseSample("ThisInAnonymousClass");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Bar");
 
@@ -348,7 +412,7 @@
     }
 
     @Test
-    public void thisInAnonymousClass() {
+    void thisInAnonymousClass() {
         CompilationUnit cu = parseSample("ThisInAnonymousClass");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Bar");
 
@@ -358,4 +422,181 @@
         assertEquals(true, type.isReferenceType());
         assertEquals(true, type.asReferenceType().getTypeDeclaration() instanceof JavaParserAnonymousClassDeclaration);
     }
+
+    @Test
+    void resolveMethodCallWithScopeDeclarationInSwitchEntryStmt() {
+        CompilationUnit cu = parseSample("TryInSwitch");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "TryInSwitch");
+
+        MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
+
+        MethodCallExpr callExpr = method.getBody().get().getStatement(1)
+                .asSwitchStmt().getEntry(0).getStatement(1)
+                .asTryStmt().getTryBlock().getStatement(1)
+                .asExpressionStmt().getExpression()
+                .asMethodCallExpr();
+
+        SymbolReference<ResolvedMethodDeclaration> reference = JavaParserFacade.get(new ReflectionTypeSolver()).solve(callExpr);
+
+        assertTrue(reference.isSolved());
+        assertEquals("java.io.File.delete()", reference.getCorrespondingDeclaration().getQualifiedSignature());
+    }
+
+    @Test
+    void complexTypeSolving() {
+        CompilationUnit cu = parseSample("ComplexTypeResolving");
+        ClassOrInterfaceDeclaration mainClass = Navigator.demandClass(cu, "Main");
+
+        ClassOrInterfaceDeclaration childDec = (ClassOrInterfaceDeclaration) mainClass.getMember(1);
+        ExpressionStmt stmt =
+                (ExpressionStmt) Navigator.demandMethod(childDec, "foo").getBody().get().getStatement(0);
+        ReferenceTypeImpl resolvedType =
+                (ReferenceTypeImpl) JavaParserFacade.get(new ReflectionTypeSolver()).getType(stmt.getExpression());
+        ClassOrInterfaceDeclaration resolvedTypeDeclaration
+                = ((JavaParserClassDeclaration) resolvedType.getTypeDeclaration()).getWrappedNode();
+
+        assertEquals(mainClass, resolvedTypeDeclaration.getParentNode().get());
+    }
+
+    @Test
+    void resolveMethodCallOfMethodInMemberClassOfAnotherClass() {
+        CompilationUnit cu = parseSample("NestedClasses");
+        ClassOrInterfaceDeclaration classA = Navigator.demandClass(cu, "A");
+
+        MethodDeclaration method = Navigator.demandMethod(classA, "foo");
+
+        MethodCallExpr callExpr = method.getBody().get().getStatement(1)
+                .asExpressionStmt().getExpression().asMethodCallExpr();
+
+        SymbolReference<ResolvedMethodDeclaration> reference = JavaParserFacade.get(new ReflectionTypeSolver())
+                .solve(callExpr);
+
+        assertTrue(reference.isSolved());
+        assertEquals("X.Y.bar()", reference.getCorrespondingDeclaration().getQualifiedSignature());
+    }
+
+    @Test
+    void resolveMethodCallOfMethodInMemberInterfaceOfAnotherInterface() {
+        CompilationUnit cu = parseSample("NestedInterfaces");
+        ClassOrInterfaceDeclaration classA = Navigator.demandInterface(cu, "A");
+
+        MethodDeclaration method = Navigator.demandMethod(classA, "foo");
+
+        MethodCallExpr callExpr = method.getBody().get().getStatement(1)
+                .asExpressionStmt().getExpression().asMethodCallExpr();
+
+        SymbolReference<ResolvedMethodDeclaration> reference = JavaParserFacade.get(new ReflectionTypeSolver())
+                .solve(callExpr);
+
+        assertTrue(reference.isSolved());
+        assertEquals("X.Y.bar()", reference.getCorrespondingDeclaration().getQualifiedSignature());
+    }
+
+    @Test
+    void resolveMethodCallOfMethodInMemberInterfaceWithIdenticalNameOfAnotherInterface() {
+        CompilationUnit cu = parseSample("NestedInterfacesWithIdenticalNames");
+        ClassOrInterfaceDeclaration classA = Navigator.demandInterface(cu, "A");
+
+        MethodDeclaration method = Navigator.demandMethod(classA, "foo");
+
+        MethodCallExpr callExpr = method.getBody().get().getStatement(1)
+                .asExpressionStmt().getExpression().asMethodCallExpr();
+
+        SymbolReference<ResolvedMethodDeclaration> reference = JavaParserFacade.get(new ReflectionTypeSolver())
+                .solve(callExpr);
+
+        assertTrue(reference.isSolved());
+        assertEquals("X.A.bar()", reference.getCorrespondingDeclaration().getQualifiedSignature());
+    }
+
+    @Test
+    void resolveLocalMethodInClassExtendingUnknownClass() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get field access expression
+        CompilationUnit cu = parseSample("ClassExtendingUnknownClass");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassExtendingUnknownClass");
+        MethodDeclaration method = Navigator.demandMethod(clazz, "foo");
+        MethodCallExpr methodCallExpr = method.getBody().get().getStatements().get(0).asExpressionStmt()
+                .getExpression().asMethodCallExpr();
+
+        // resolve field access expression
+        ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
+
+        // check that the expected method declaration equals the resolved method declaration
+        assertEquals("ClassExtendingUnknownClass.bar(java.lang.String)", resolvedMethodDeclaration.getQualifiedSignature());
+    }
+
+    @Test
+    void resolveCorrectMethodWithComplexOverloading1() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get method call expression
+        CompilationUnit cu = parseSample("OverloadedMethods");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "OverloadedMethods");
+        MethodDeclaration testingMethod = Navigator.demandMethod(clazz, "testComplex1");
+        MethodCallExpr methodCallExpr = testingMethod.getBody().get().getStatements().get(0).asExpressionStmt()
+                .getExpression().asMethodCallExpr();
+
+        // resolve method call expression
+        ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
+
+        assertEquals("OverloadedMethods.complexOverloading1(java.lang.String, java.lang.String)", resolvedMethodDeclaration.getQualifiedSignature());
+    }
+
+    @Test
+    void resolveCorrectMethodWithComplexOverloading2() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get method call expression
+        CompilationUnit cu = parseSample("OverloadedMethods");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "OverloadedMethods");
+        MethodDeclaration testingMethod = Navigator.demandMethod(clazz, "testComplex2");
+        MethodCallExpr methodCallExpr = testingMethod.getBody().get().getStatements().get(0).asExpressionStmt()
+                .getExpression().asMethodCallExpr();
+
+        // resolve method call expression
+        ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
+
+        assertEquals("OverloadedMethods.complexOverloading2(java.lang.String...)", resolvedMethodDeclaration.getQualifiedSignature());
+    }
+
+    @Test
+    void resolveCorrectMethodWithComplexOverloading3() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get method call expression
+        CompilationUnit cu = parseSample("OverloadedMethods");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "OverloadedMethods");
+        MethodDeclaration testingMethod = Navigator.demandMethod(clazz, "testComplex3");
+        MethodCallExpr methodCallExpr = testingMethod.getBody().get().getStatements().get(0).asExpressionStmt()
+                .getExpression().asMethodCallExpr();
+
+        // resolve method call expression
+        ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
+
+        assertEquals("OverloadedMethods.complexOverloading3(long)", resolvedMethodDeclaration.getQualifiedSignature());
+    }
+
+    @Test
+    void resolveCorrectMethodWithComplexOverloading4() {
+        // configure symbol solver before parsing
+        StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver()));
+
+        // parse compilation unit and get method call expression
+        CompilationUnit cu = parseSample("OverloadedMethods");
+        ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "OverloadedMethods");
+        MethodDeclaration testingMethod = Navigator.demandMethod(clazz, "testComplex4");
+        MethodCallExpr methodCallExpr = testingMethod.getBody().get().getStatements().get(0).asExpressionStmt()
+                .getExpression().asMethodCallExpr();
+
+        // resolve method call expression
+        ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
+
+        assertEquals("OverloadedMethods.complexOverloading4(long, int)", resolvedMethodDeclaration.getQualifiedSignature());
+    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionWithJavassistTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionWithJavassistTest.java
new file mode 100644
index 0000000..94d24ee
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionWithJavassistTest.java
@@ -0,0 +1,56 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.utils.Log;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MethodsResolutionWithJavassistTest extends AbstractResolutionTest {
+
+    @AfterEach
+    void resetConfiguration() {
+        StaticJavaParser.setConfiguration(new ParserConfiguration());
+        Log.setAdapter(new Log.SilentAdapter());
+    }
+
+    @Test
+    public void testOverloadedMethods() throws Exception {
+        CompilationUnit cu = parseSample("OverloadedMethodCall");
+
+        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
+        typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar")));
+        typeSolver.add(new ReflectionTypeSolver());
+
+        Context context = new CompilationUnitContext(cu, typeSolver);
+        ClassOrInterfaceDeclaration classA = Navigator.demandClass(cu, "OverloadedMethodCall");
+        MethodDeclaration method = Navigator.demandMethod(classA, "foo");
+
+        List<MethodCallExpr> calls = method.findAll(MethodCallExpr.class, n -> n.getNameAsString().equals("accept"));
+        assertEquals(2, calls.size());
+
+        // node.accept((GenericVisitor) null, null);
+        MethodUsage methodUsage1 = JavaParserFacade.get(typeSolver).solveMethodAsUsage(calls.get(0));
+        assertEquals("com.github.javaparser.ast.visitor.GenericVisitor<R, A>", methodUsage1.getParamType(0).describe());
+
+        // node.accept((VoidVisitor) null, null);
+        MethodUsage methodUsage2 = JavaParserFacade.get(typeSolver).solveMethodAsUsage(calls.get(1));
+        assertEquals("com.github.javaparser.ast.visitor.VoidVisitor<A>", methodUsage2.getParamType(0).describe());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/NotQuiteCyclicParentTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/NotQuiteCyclicParentTest.java
new file mode 100644
index 0000000..5375a22
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/NotQuiteCyclicParentTest.java
@@ -0,0 +1,36 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class NotQuiteCyclicParentTest extends AbstractResolutionTest {
+
+	@Test
+	void testSimilarNameInterface() {
+		CompilationUnit cu = parseSample("NotQuiteCyclicParent");
+		ClassOrInterfaceDeclaration clazz = Navigator.demandInterface(cu, "NotQuiteCyclicParent");
+		MethodDeclaration method = Navigator.demandMethod(clazz, "main");
+		VariableDeclarationExpr varDec =
+				(VariableDeclarationExpr) ((ExpressionStmt) method.getBody().get().getStatement(0)).getExpression();
+
+		try {
+			ResolvedType ref = JavaParserFacade.get(new ReflectionTypeSolver()).getType(varDec);
+		} catch (UnsolvedSymbolException e) {
+			return;
+		}
+
+		fail("We shouldn't be able to resolve the type (it is not defined).");
+	}
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/QualifiedNameResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/QualifiedNameResolutionTest.java
index 906ac68..4ccf8bb 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/QualifiedNameResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/QualifiedNameResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.NameExpr;
@@ -25,15 +24,15 @@
 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class QualifiedNameResolutionTest extends AbstractResolutionTest {
+class QualifiedNameResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void resolveLocalVariableInParentOfParent() {
+    void resolveLocalVariableInParentOfParent() {
         CompilationUnit cu = parseSample("QualifiedNameTest");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "QualifiedNameTest");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "foo1");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/StatementContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/StatementContextResolutionTest.java
index b96abf7..c9f7d13 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/StatementContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/StatementContextResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.MethodCallExpr;
@@ -28,15 +27,15 @@
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class StatementContextResolutionTest extends AbstractResolutionTest {
+class StatementContextResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void resolveLocalVariableInParentOfParent() {
+    void resolveLocalVariableInParentOfParent() {
         CompilationUnit cu = parseSample("LocalVariableInParent");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "LocalVariableInParent");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "foo1");
@@ -48,7 +47,7 @@
     }
 
     @Test
-    public void resolveLocalVariableInParent() {
+    void resolveLocalVariableInParent() {
         CompilationUnit cu = parseSample("LocalVariableInParent");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "LocalVariableInParent");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "foo3");
@@ -60,7 +59,7 @@
     }
 
     @Test
-    public void resolveLocalVariableInSameParent() {
+    void resolveLocalVariableInSameParent() {
         CompilationUnit cu = parseSample("LocalVariableInParent");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "LocalVariableInParent");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "foo2");
@@ -72,7 +71,7 @@
     }
 
     @Test
-    public void resolveLocalAndSeveralAnnidatedLevels() {
+    void resolveLocalAndSeveralAnnidatedLevels() {
         CompilationUnit cu = parseSample("LocalVariableInParent");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "LocalVariableInParent");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "foo4");
@@ -89,7 +88,7 @@
     }
 
     @Test
-    public void resolveMethodOnGenericClass() {
+    void resolveMethodOnGenericClass() {
         CompilationUnit cu = parseSample("LocalVariableInParent");
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "LocalVariableInParent");
         MethodDeclaration method = Navigator.demandMethod(referencesToField, "foo5");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverTest.java
index eafe601..3db4bc4 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverTest.java
@@ -16,85 +16,79 @@
 
 package com.github.javaparser.symbolsolver.resolution;
 
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.visitor.VoidVisitor;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.symbolsolver.AbstractTest;
-import com.github.javaparser.symbolsolver.javaparser.Navigator;
-import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * @author Federico Tomassetti
  */
-public class SymbolSolverTest extends AbstractTest {
+class SymbolSolverTest extends AbstractSymbolResolutionTest {
 
     private TypeSolver typeSolverNewCode;
     private SymbolSolver symbolSolver;
 
-    @Before
-    public void setup() {
-
-        File srcNewCode = adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-core"));
+    @BeforeEach
+    void setup() {
+        Path srcNewCode = adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-core");
         CombinedTypeSolver combinedTypeSolverNewCode = new CombinedTypeSolver();
         combinedTypeSolverNewCode.add(new ReflectionTypeSolver());
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(srcNewCode));
-        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath(new File("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"))));
+        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(srcNewCode, new LeanParserConfiguration()));
+        combinedTypeSolverNewCode.add(new JavaParserTypeSolver(adaptPath("src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources"), new LeanParserConfiguration()));
         typeSolverNewCode = combinedTypeSolverNewCode;
 
         symbolSolver = new SymbolSolver(typeSolverNewCode);
     }
 
     @Test
-    public void testSolveSymbolUnexisting() {
+    void testSolveSymbolUnexisting() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         SymbolReference<? extends ResolvedValueDeclaration> res = symbolSolver.solveSymbolInType(constructorDeclaration, "unexisting");
-        assertEquals(false, res.isSolved());
+        assertFalse(res.isSolved());
     }
 
     @Test
-    public void testSolveSymbolToDeclaredField() {
+    void testSolveSymbolToDeclaredField() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         SymbolReference<? extends ResolvedValueDeclaration> res = symbolSolver.solveSymbolInType(constructorDeclaration, "name");
-        assertEquals(true, res.isSolved());
-        assertEquals(true, res.getCorrespondingDeclaration().isField());
+        assertTrue(res.isSolved());
+        assertTrue(res.getCorrespondingDeclaration().isField());
     }
 
     @Test
-    public void testSolveSymbolToInheritedPublicField() {
+    void testSolveSymbolToInheritedPublicField() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         SymbolReference<? extends ResolvedValueDeclaration> res = symbolSolver.solveSymbolInType(constructorDeclaration, "NODE_BY_BEGIN_POSITION");
-        assertEquals(true, res.isSolved());
-        assertEquals(true, res.getCorrespondingDeclaration().isField());
+        assertTrue(res.isSolved());
+        assertTrue(res.getCorrespondingDeclaration().isField());
     }
 
     @Test
-    public void testSolveSymbolToInheritedPrivateField() {
+    void testSolveSymbolToInheritedPrivateField() {
         JavaParserClassDeclaration constructorDeclaration = (JavaParserClassDeclaration) typeSolverNewCode.solveType("com.github.javaparser.ast.body.ConstructorDeclaration");
 
         SymbolReference<? extends ResolvedValueDeclaration> res = symbolSolver.solveSymbolInType(constructorDeclaration, "parentNode");
-        assertEquals(false, res.isSolved());
+        assertFalse(res.isSolved());
     }
 
     @Test
-    public void testSolvePackageLocalClass() {
+    void testSolvePackageLocalClass() {
         assertTrue(typeSolverNewCode.solveType("com.github.javaparser.FooClass").isClass());
     }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistClassTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistClassTest.java
index cf103f1..c67ccd6 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistClassTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistClassTest.java
@@ -18,21 +18,22 @@
 
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
+import java.nio.file.Path;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class SymbolSolverWithJavassistClassTest extends AbstractTest {
+class SymbolSolverWithJavassistClassTest extends AbstractSymbolResolutionTest {
     private TypeSolver typeSolver;
     private SymbolSolver symbolSolver;
     private JavassistClassDeclaration classDeclarationConcreteClass;
@@ -43,10 +44,10 @@
     private JavassistClassDeclaration classDeclarationSubClassExcludedJar;
     private JavassistClassDeclaration classDeclarationInterfaceUserExcludedJar;
 
-    @Before
-    public void setup() throws IOException {
-        final String pathToMainJar = adaptPath("src/test/resources/javassist_symbols/main_jar/main_jar.jar");
-        final String pathToIncludedJar = adaptPath("src/test/resources/javassist_symbols/included_jar/included_jar.jar");
+    @BeforeEach
+    void setup() throws IOException {
+        final Path pathToMainJar = adaptPath("src/test/resources/javassist_symbols/main_jar/main_jar.jar");
+        final Path pathToIncludedJar = adaptPath("src/test/resources/javassist_symbols/included_jar/included_jar.jar");
         typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToIncludedJar), new JarTypeSolver(pathToMainJar), new ReflectionTypeSolver());
 
         symbolSolver = new SymbolSolver(typeSolver);
@@ -61,17 +62,17 @@
     }
 
     @Test
-    public void testSolveSymbolInTypeCanSolveFirstOwnField() {
+    void testSolveSymbolInTypeCanSolveFirstOwnField() {
         assertCanSolveSymbol("STATIC_STRING", classDeclarationConcreteClass);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanSolveSecondOwnField() {
+    void testSolveSymbolInTypeCanSolveSecondOwnField() {
         assertCanSolveSymbol("SECOND_STRING", classDeclarationConcreteClass);
     }
 
     @Test
-    public void testSolveSymbolInTypeCantResolveNonExistentField() {
+    void testSolveSymbolInTypeCantResolveNonExistentField() {
         SymbolReference<? extends ResolvedValueDeclaration> solvedSymbol = symbolSolver.solveSymbolInType(classDeclarationConcreteClass, "FIELD_THAT_DOES_NOT_EXIST");
 
         assertFalse(solvedSymbol.isSolved());
@@ -87,17 +88,17 @@
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInSuper() {
+    void testSolveSymbolInTypeCanResolveFieldInSuper() {
         assertCanSolveSymbol("SUPER_FIELD", classDeclarationSubClassOwnJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInSuperIncludedJar() {
+    void testSolveSymbolInTypeCanResolveFieldInSuperIncludedJar() {
         assertCanSolveSymbol("SUPER_FIELD", classDeclarationSubClassIncludedJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInSuperExcludedJar() {
+    void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInSuperExcludedJar() {
         try {
             symbolSolver.solveSymbolInType(classDeclarationSubClassExcludedJar, "SUPER_FIELD");
         } catch (Exception e) {
@@ -109,17 +110,17 @@
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInInterface() {
+    void testSolveSymbolInTypeCanResolveFieldInInterface() {
         assertCanSolveSymbol("INTERFACE_FIELD", classDeclarationInterfaceUserOwnJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInInterfaceIncludedJar() {
+    void testSolveSymbolInTypeCanResolveFieldInInterfaceIncludedJar() {
         assertCanSolveSymbol("INTERFACE_FIELD", classDeclarationInterfaceUserIncludedJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInInterfaceExcludedJar() {
+    void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInInterfaceExcludedJar() {
         try {
             symbolSolver.solveSymbolInType(classDeclarationInterfaceUserExcludedJar, "INTERFACE_FIELD");
         } catch (Exception e) {
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistEnumTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistEnumTest.java
index 120d2f1..b0ece1c 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistEnumTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistEnumTest.java
@@ -2,22 +2,22 @@
 
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.javassistmodel.JavassistEnumDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
+import java.nio.file.Path;
 
-import static org.junit.Assert.*;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class SymbolSolverWithJavassistEnumTest extends AbstractTest {
+class SymbolSolverWithJavassistEnumTest extends AbstractSymbolResolutionTest {
     private TypeSolver typeSolver;
     private SymbolSolver symbolSolver;
     private JavassistEnumDeclaration enumDeclarationConcrete;
@@ -25,10 +25,10 @@
     private JavassistEnumDeclaration enumDeclarationInterfaceUserIncludedJar;
     private JavassistEnumDeclaration enumDeclarationInterfaceUserExcludedJar;
 
-    @Before
-    public void setup() throws IOException {
-        final String pathToMainJar = adaptPath("src/test/resources/javassist_symbols/main_jar/main_jar.jar");
-        final String pathToIncludedJar = adaptPath("src/test/resources/javassist_symbols/included_jar/included_jar.jar");
+    @BeforeEach
+    void setup() throws IOException {
+        final Path pathToMainJar = adaptPath("src/test/resources/javassist_symbols/main_jar/main_jar.jar");
+        final Path pathToIncludedJar = adaptPath("src/test/resources/javassist_symbols/included_jar/included_jar.jar");
         typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToIncludedJar), new JarTypeSolver(pathToMainJar), new ReflectionTypeSolver());
 
         symbolSolver = new SymbolSolver(typeSolver);
@@ -40,27 +40,27 @@
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFirstEnumValue() {
+    void testSolveSymbolInTypeCanResolveFirstEnumValue() {
         assertCanSolveSymbol("ENUM_VAL_ONE", enumDeclarationConcrete);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveSecondEnumValue() {
+    void testSolveSymbolInTypeCanResolveSecondEnumValue() {
         assertCanSolveSymbol("ENUM_VAL_TWO", enumDeclarationConcrete);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFirstNormalField() {
+    void testSolveSymbolInTypeCanResolveFirstNormalField() {
         assertCanSolveSymbol("STATIC_STRING", enumDeclarationConcrete);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveSecondNormalField() {
+    void testSolveSymbolInTypeCanResolveSecondNormalField() {
         assertCanSolveSymbol("SECOND_STRING", enumDeclarationConcrete);
     }
 
     @Test
-    public void testSolveSymbolInTypeCantResolveNonExistentField() {
+    void testSolveSymbolInTypeCantResolveNonExistentField() {
         SymbolReference<? extends ResolvedValueDeclaration> solvedSymbol = symbolSolver.solveSymbolInType(enumDeclarationConcrete, "FIELD_THAT_DOES_NOT_EXIST");
 
         assertFalse(solvedSymbol.isSolved());
@@ -76,17 +76,17 @@
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInInterface() {
+    void testSolveSymbolInTypeCanResolveFieldInInterface() {
         assertCanSolveSymbol("INTERFACE_FIELD", enumDeclarationInterfaceUserOwnJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInInterfaceIncludedJar() {
+    void testSolveSymbolInTypeCanResolveFieldInInterfaceIncludedJar() {
         assertCanSolveSymbol("INTERFACE_FIELD", enumDeclarationInterfaceUserIncludedJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInInterfaceExcludedJar() {
+    void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInInterfaceExcludedJar() {
         try {
             symbolSolver.solveSymbolInType(enumDeclarationInterfaceUserExcludedJar, "INTERFACE_FIELD");
         } catch (Exception e) {
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistInterfaceTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistInterfaceTest.java
index 7745e81..a494551 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistInterfaceTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/SymbolSolverWithJavassistInterfaceTest.java
@@ -2,21 +2,22 @@
 
 import com.github.javaparser.resolution.UnsolvedSymbolException;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
-import com.github.javaparser.symbolsolver.AbstractTest;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
 import com.github.javaparser.symbolsolver.javassistmodel.JavassistInterfaceDeclaration;
 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
+import java.nio.file.Path;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
-public class SymbolSolverWithJavassistInterfaceTest extends AbstractTest {
+class SymbolSolverWithJavassistInterfaceTest extends AbstractSymbolResolutionTest {
     private TypeSolver typeSolver;
     private SymbolSolver symbolSolver;
     private JavassistInterfaceDeclaration interfaceDeclarationStandalone;
@@ -24,10 +25,10 @@
     private JavassistInterfaceDeclaration interfaceDeclarationSubInterfaceIncludedJar;
     private JavassistInterfaceDeclaration interfaceDeclarationSubInterfaceExcludedJar;
 
-    @Before
-    public void setup() throws IOException {
-        final String pathToMainJar = adaptPath("src/test/resources/javassist_symbols/main_jar/main_jar.jar");
-        final String pathToIncludedJar = adaptPath("src/test/resources/javassist_symbols/included_jar/included_jar.jar");
+    @BeforeEach
+    void setup() throws IOException {
+        final Path pathToMainJar = adaptPath("src/test/resources/javassist_symbols/main_jar/main_jar.jar");
+        final Path pathToIncludedJar = adaptPath("src/test/resources/javassist_symbols/included_jar/included_jar.jar");
         typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToIncludedJar), new JarTypeSolver(pathToMainJar), new ReflectionTypeSolver());
 
         symbolSolver = new SymbolSolver(typeSolver);
@@ -39,17 +40,17 @@
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFirstNormalField() {
+    void testSolveSymbolInTypeCanResolveFirstNormalField() {
         assertCanSolveSymbol("STATIC_STRING", interfaceDeclarationStandalone);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveSecondNormalField() {
+    void testSolveSymbolInTypeCanResolveSecondNormalField() {
         assertCanSolveSymbol("SECOND_STRING", interfaceDeclarationStandalone);
     }
 
     @Test
-    public void testSolveSymbolInTypeCantResolveNonExistentField() {
+    void testSolveSymbolInTypeCantResolveNonExistentField() {
         SymbolReference<? extends ResolvedValueDeclaration> solvedSymbol = symbolSolver.solveSymbolInType(interfaceDeclarationStandalone, "FIELD_THAT_DOES_NOT_EXIST");
 
         assertFalse(solvedSymbol.isSolved());
@@ -65,17 +66,17 @@
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInExtendedInterfaceOwnJar() {
+    void testSolveSymbolInTypeCanResolveFieldInExtendedInterfaceOwnJar() {
         assertCanSolveSymbol("INTERFACE_FIELD", interfaceDeclarationSubInterfaceOwnJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeCanResolveFieldInExtendedInterfaceIncludedJar() {
+    void testSolveSymbolInTypeCanResolveFieldInExtendedInterfaceIncludedJar() {
         assertCanSolveSymbol("INTERFACE_FIELD", interfaceDeclarationSubInterfaceIncludedJar);
     }
 
     @Test
-    public void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInExtendedInterfaceExcludedJar() {
+    void testSolveSymbolInTypeThrowsExceptionOnResolveFieldInExtendedInterfaceExcludedJar() {
         try {
             symbolSolver.solveSymbolInType(interfaceDeclarationSubInterfaceExcludedJar, "INTERFACE_FIELD");
         } catch (Exception e) {
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/TypeInClassWithAnnotationAncestorTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/TypeInClassWithAnnotationAncestorTest.java
new file mode 100644
index 0000000..c78932c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/TypeInClassWithAnnotationAncestorTest.java
@@ -0,0 +1,26 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class TypeInClassWithAnnotationAncestorTest extends AbstractResolutionTest {
+
+	@Test
+	void resolveStringReturnType() {
+		CompilationUnit cu = parseSample("ClassWithAnnotationAncestor");
+		ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "ClassWithAnnotationAncestor");
+		MethodDeclaration method = Navigator.demandMethod(clazz, "testMethod");
+		ResolvedType type = JavaParserFacade.get(new ReflectionTypeSolver())
+				                    .convertToUsage(method.getType(), method.getType());
+		assertFalse(type.isTypeVariable());
+		assertEquals("java.lang.String", type.describe());
+	}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/TypeResolutionWithSameNameTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/TypeResolutionWithSameNameTest.java
new file mode 100644
index 0000000..ad1e465
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/TypeResolutionWithSameNameTest.java
@@ -0,0 +1,85 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.StaticJavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+public class TypeResolutionWithSameNameTest extends AbstractResolutionTest {
+
+
+    /*
+     * abstract class extends_duplicate.DuplicateTypeName
+     * class extends_duplicate.A extends extends_duplicate.DuplicateTypeName
+     * class extends_duplicate.A.DuplicateTypeName extends extends_duplicate.A
+     */
+    @Test
+    void testTypesWithSameNameInPackageAndNested_directExtends() throws IOException {
+        Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src1");
+        Path extendsTypePath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/A.java");
+
+        JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
+        StaticJavaParser
+                .getConfiguration()
+                .setSymbolResolver(new JavaSymbolSolver(javaParserTypeSolver));
+
+        CompilationUnit cu = StaticJavaParser.parse(extendsTypePath);
+        ClassOrInterfaceDeclaration extendingTypeClass = Navigator.demandClass(cu, "A");
+
+        // Attempt to resolve `DuplicateTypeName` from `class ExtendingType extends **DuplicateTypeName**`
+        assumeTrue(extendingTypeClass.getExtendedTypes().size() > 0);
+        ClassOrInterfaceType extendedType = extendingTypeClass.getExtendedTypes(0);
+        ResolvedReferenceType resolvedExtendedType = extendedType.resolve();
+
+        // Verify qualified name matches the non-nested class in the same package.
+        // Note verbose assertions show both the "correct" expected value, and the erroneous value to be avoided.
+        String qualifiedName = resolvedExtendedType.getQualifiedName();
+        assertEquals("extends_duplicate.DuplicateTypeName", qualifiedName, "Error - not resolved to interface in separate file.");
+        assertNotEquals("extends_duplicate.A.DuplicateTypeName", qualifiedName, "Error - resolved to nested class.");
+    }
+
+
+    /*
+     * interface implements_duplicate.DuplicateTypeName
+     * class implements_duplicate.class A implements implements_duplicate.DuplicateTypeName
+     * class implements_duplicate.A.DuplicateTypeName extends implements_duplicate.A
+     */
+    @Test
+    void testTypesWithSameNameInPackageAndNested_directImplements() throws IOException {
+        Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src2");
+        Path implementingTypePath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/A.java");
+
+        JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
+        StaticJavaParser
+                .getConfiguration()
+                .setSymbolResolver(new JavaSymbolSolver(javaParserTypeSolver));
+
+        CompilationUnit cu = StaticJavaParser.parse(implementingTypePath);
+        ClassOrInterfaceDeclaration implementingTypeClass = Navigator.demandClass(cu, "A");
+
+        // Attempt to resolve `DuplicateTypeName` from `class ImplementingType implements **DuplicateTypeName**`
+        assumeTrue(implementingTypeClass.getImplementedTypes().size() > 0);
+        ClassOrInterfaceType implementedType = implementingTypeClass.getImplementedTypes(0);
+        ResolvedReferenceType resolvedImplementedType = implementedType.resolve();
+
+        // Verify qualified name matches the non-nested class in the same package.
+        // Note verbose assertions show both the "correct" expected value, and the erroneous value to be avoided.
+        String qualifiedName = resolvedImplementedType.getQualifiedName();
+        assertEquals("implements_duplicate.DuplicateTypeName", qualifiedName, "Error - not resolved to interface in separate file.");
+        assertNotEquals("implements_duplicate.A.DuplicateTypeName", qualifiedName, "Error - resolved to nested class.");
+    }
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/UnknownMethodsResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/UnknownMethodsResolutionTest.java
new file mode 100644
index 0000000..4ce7947
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/UnknownMethodsResolutionTest.java
@@ -0,0 +1,41 @@
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class UnknownMethodsResolutionTest extends AbstractResolutionTest {
+
+	@Test
+	void testUnknownMethod1() {
+		assertThrows(UnsolvedSymbolException.class, () -> {
+		    CompilationUnit cu = parseSample("UnknownMethods");
+		ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "UnknownMethods");
+		MethodDeclaration method = Navigator.demandMethod(clazz, "test1");
+		MethodCallExpr methodCallExpr = method.getBody().get().getStatement(0).asExpressionStmt().getExpression().asMethodCallExpr();
+		SymbolReference<ResolvedMethodDeclaration> ref = JavaParserFacade.get(new ReflectionTypeSolver()).solve(methodCallExpr);
+});
+						
+}
+
+	@Test
+	void testUnknownMethod2() {
+		assertThrows(UnsolvedSymbolException.class, () -> {
+		    CompilationUnit cu = parseSample("UnknownMethods");
+		ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "UnknownMethods");
+		MethodDeclaration method = Navigator.demandMethod(clazz, "test2");
+		MethodCallExpr methodCallExpr = method.getBody().get().getStatement(1).asExpressionStmt().getExpression().asMethodCallExpr();
+		SymbolReference<ResolvedMethodDeclaration> ref = JavaParserFacade.get(new ReflectionTypeSolver()).solve(methodCallExpr);
+});
+						
+}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/VariadicResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/VariadicResolutionTest.java
index 48c0ca7..04a991b 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/VariadicResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/VariadicResolutionTest.java
@@ -30,17 +30,18 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
 import java.util.List;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class VariadicResolutionTest extends AbstractResolutionTest {
+class VariadicResolutionTest extends AbstractResolutionTest {
 
 	@Test
-    public void issue7() {
+    void issue7() {
         CompilationUnit cu = parseSample("Generics_issue7");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "SomeCollection");
 
@@ -56,7 +57,7 @@
     }
 	
 	@Test
-    public void methodCallWithReferenceTypeAsVaridicArgumentIsSolved() {
+    void methodCallWithReferenceTypeAsVaridicArgumentIsSolved() {
         CompilationUnit cu = parseSample("MethodCalls");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
 
@@ -70,7 +71,7 @@
     }
 
     @Test
-    public void resolveVariadicMethodWithGenericArgument() {
+    void resolveVariadicMethodWithGenericArgument() {
         CompilationUnit cu = parseSample("MethodCalls");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
 
@@ -84,15 +85,15 @@
     }
 
     @Test
-    public void selectMostSpecificVariadic() {
+    void selectMostSpecificVariadic() {
         CompilationUnit cu = parseSample("MethodCalls");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
 
         MethodDeclaration method = Navigator.demandMethod(clazz, "variadicTest");
         List<MethodCallExpr> calls = method.findAll(MethodCallExpr.class);
 
-        File src = adaptPath(new File("src/test/resources"));
-        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(src));
+        Path src = adaptPath("src/test/resources");
+        TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(src, new LeanParserConfiguration()));
 
         JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
         MethodUsage call1 = javaParserFacade.solveMethodAsUsage(calls.get(0));
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/VarTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/VarTypeTest.java
index d8d0eaf..e9ab8b8 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/VarTypeTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/VarTypeTest.java
@@ -12,20 +12,21 @@
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_10;
 import static com.github.javaparser.Providers.provider;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class VarTypeTest {
+class VarTypeTest {
     private final TypeSolver typeSolver = new ReflectionTypeSolver();
     private final JavaParser javaParser = new JavaParser(new ParserConfiguration()
             .setLanguageLevel(JAVA_10)
             .setSymbolResolver(new JavaSymbolSolver(typeSolver)));
 
     @Test
-    public void resolveAPrimitive() {
+    void resolveAPrimitive() {
         CompilationUnit ast = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{void x(){var abc = 1;}}")).getResult().get();
         VarType varType = ast.findFirst(VarType.class).get();
 
@@ -35,7 +36,7 @@
     }
 
     @Test
-    public void resolveAReferenceType() {
+    void resolveAReferenceType() {
         CompilationUnit ast = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{void x(){var abc = \"\";}}")).getResult().get();
         VarType varType = ast.findFirst(VarType.class).get();
 
@@ -44,19 +45,23 @@
         assertEquals(new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver), resolvedType);
     }
 
-    @Test(expected = IllegalStateException.class)
-    public void failResolveNoInitializer() {
-        CompilationUnit ast = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{void x(){var abc;}}")).getResult().get();
+    @Test
+    void failResolveNoInitializer() {
+        assertThrows(IllegalStateException.class, () -> {
+            CompilationUnit ast = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{void x(){var abc;}}")).getResult().get();
         VarType varType = ast.findFirst(VarType.class).get();
-
         varType.resolve();
-    }
+    });
+        
+}
 
-    @Test(expected = IllegalStateException.class)
-    public void failResolveWrongLocation() {
-        CompilationUnit ast = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{void x(var x){};}")).getResult().get();
+    @Test
+    void failResolveWrongLocation() {
+        assertThrows(IllegalStateException.class, () -> {
+            CompilationUnit ast = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{void x(var x){};}")).getResult().get();
         VarType varType = ast.findFirst(VarType.class).get();
-
         varType.resolve();
-    }
+    });
+        
+}
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/ClassOrInterfaceDeclarationContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/ClassOrInterfaceDeclarationContextResolutionTest.java
index a559418..7dc1826 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/ClassOrInterfaceDeclarationContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/ClassOrInterfaceDeclarationContextResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution.javaparser.contexts;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.resolution.MethodAmbiguityException;
@@ -37,31 +36,31 @@
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
-import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Optional;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 /**
  * @author Federico Tomassetti
  */
-public class ClassOrInterfaceDeclarationContextResolutionTest extends AbstractResolutionTest {
+class ClassOrInterfaceDeclarationContextResolutionTest extends AbstractResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
     }
 
     @Test
-    public void getParentForTopClass() {
+    void getParentForTopClass() {
         CompilationUnit cu = parseSample("ClassWithTypeVariables");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
@@ -71,15 +70,14 @@
     }
 
     @Test
-    public void solveExistingGenericType() {
+    void solveExistingGenericType() {
         CompilationUnit cu = parseSample("ClassWithTypeVariables");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<ResolvedType> a = context.solveGenericType("A", new MemoryTypeSolver());
-        Optional<ResolvedType> b = context.solveGenericType("B", new MemoryTypeSolver());
-        Optional<ResolvedType> c = context.solveGenericType("C", new MemoryTypeSolver());
-
+        Optional<ResolvedType> a = context.solveGenericType("A");
+        Optional<ResolvedType> b = context.solveGenericType("B");
+        Optional<ResolvedType> c = context.solveGenericType("C");
         assertEquals(true, a.isPresent());
         assertEquals("A", a.get().describe());
         assertEquals(true, a.get().isTypeVariable());
@@ -92,399 +90,408 @@
     }
 
     @Test
-    public void solveUnexistingGenericType() {
+    void solveUnexistingGenericType() {
         CompilationUnit cu = parseSample("ClassWithTypeVariables");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<ResolvedType> d = context.solveGenericType("D", new MemoryTypeSolver());
+        Optional<ResolvedType> d = context.solveGenericType("D");
 
         assertEquals(false, d.isPresent());
     }
 
     @Test
-    public void solveSymbolReferringToDeclaredInstanceField() {
+    void solveSymbolReferringToDeclaredInstanceField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("i", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("i");
         assertEquals(true, ref.isSolved());
         assertEquals("int", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolReferringToDeclaredStaticField() {
+    void solveSymbolReferringToDeclaredStaticField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("j", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("j");
         assertEquals(true, ref.isSolved());
         assertEquals("long", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolReferringToInheritedInstanceField() {
+    void solveSymbolReferringToInheritedInstanceField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("k", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("k");
         assertEquals(true, ref.isSolved());
         assertEquals("boolean", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolReferringToInterfaceInheritedInstanceField() {
+    void solveSymbolReferringToInterfaceInheritedInstanceField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("o", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("o");
         assertEquals(true, ref.isSolved());
         assertEquals("int", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolReferringToInheritedStaticField() {
+    void solveSymbolReferringToInheritedStaticField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("m", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("m");
         assertEquals(true, ref.isSolved());
         assertEquals("char", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolReferringToUnknownElement() {
+    void solveSymbolReferringToUnknownElement() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("zzz", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("zzz");
         assertEquals(false, ref.isSolved());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToDeclaredInstanceField() {
+    void solveSymbolAsValueReferringToDeclaredInstanceField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("i", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("i");
         assertEquals(true, ref.isPresent());
         assertEquals("int", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToDeclaredStaticField() {
+    void solveSymbolAsValueReferringToDeclaredStaticField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("j", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("j");
         assertEquals(true, ref.isPresent());
         assertEquals("long", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToInheritedInstanceField() {
+    void solveSymbolAsValueReferringToInheritedInstanceField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("k", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("k");
         assertEquals(true, ref.isPresent());
         assertEquals("boolean", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToInterfaceInheritedInstanceField() {
+    void solveSymbolAsValueReferringToInterfaceInheritedInstanceField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         ClassOrInterfaceDeclarationContext context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("o", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("o");
         assertEquals(true, ref.isPresent());
         assertEquals("int", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToInheritedStaticField() {
+    void solveSymbolAsValueReferringToInheritedStaticField() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("m", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("m");
         assertEquals(true, ref.isPresent());
         assertEquals("char", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToUnknownElement() {
+    void solveSymbolAsValueReferringToUnknownElement() {
         CompilationUnit cu = parseSample("ClassWithSymbols");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("zzz", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("zzz");
         assertEquals(false, ref.isPresent());
     }
 
     @Test
-    public void solveTypeRefToItself() {
+    void solveTypeRefToItself() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("A", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("A");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToUnexisting() {
+    void solveTypeRefToUnexisting() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Foo", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Foo");
         assertEquals(false, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToObject() {
+    void solveTypeRefToObject() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Object", new ReflectionTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Object");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToJavaLangObject() {
+    void solveTypeRefToJavaLangObject() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("java.lang.Object", new ReflectionTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("java.lang.Object");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToInternalClass() {
+    void solveTypeRefToInternalClass() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("B", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("B");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToInternalEnum() {
+    void solveTypeRefToInternalEnum() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("E", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("E");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToInternalOfInternalClass() {
+    void solveTypeRefToInternalOfInternalClass() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("C", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("C");
         assertEquals(false, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToAnotherClassInFile() {
+    void solveTypeRefToAnotherClassInFile() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Super", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Super");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToQualifiedInternalClass() {
+    void solveTypeRefToQualifiedInternalClass() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("A.B", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("A.B");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToQualifiedInternalOfInternalClass() {
+    void solveTypeRefToQualifiedInternalOfInternalClass() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("B.C", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("B.C");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveTypeRefToMoreQualifiedInternalOfInternalClass() {
+    void solveTypeRefToMoreQualifiedInternalOfInternalClass() {
         CompilationUnit cu = parseSample("ClassWithTypes");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("A.B.C", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("A.B.C");
         assertEquals(true, ref.isSolved());
     }
 
     @Test
-    public void solveMethodSimpleCase() {
+    void solveMethodSimpleCase() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo0", ImmutableList.of(), false, new ReflectionTypeSolver());
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo0", ImmutableList.of(), false);
         assertEquals(true, ref.isSolved());
         assertEquals("A", ref.getCorrespondingDeclaration().declaringType().getName());
         assertEquals(0, ref.getCorrespondingDeclaration().getNumberOfParams());
     }
 
     @Test
-    public void solveMethodOverrideCase() {
+    void solveMethodOverrideCase() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo1", ImmutableList.of(), false, new ReflectionTypeSolver());
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo1", ImmutableList.of(), false);
         assertEquals(true, ref.isSolved());
         assertEquals("A", ref.getCorrespondingDeclaration().declaringType().getName());
         assertEquals(0, ref.getCorrespondingDeclaration().getNumberOfParams());
     }
 
     @Test
-    public void solveMethodInheritedCase() {
+    void solveMethodInheritedCase() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo2", ImmutableList.of(), false, new ReflectionTypeSolver());
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo2", ImmutableList.of(), false);
         assertEquals(true, ref.isSolved());
         assertEquals("Super", ref.getCorrespondingDeclaration().declaringType().getName());
         assertEquals(0, ref.getCorrespondingDeclaration().getNumberOfParams());
     }
 
     @Test
-    public void solveMethodWithPrimitiveParameters() {
+    void solveMethodWithPrimitiveParameters() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
         ResolvedType intType = ResolvedPrimitiveType.INT;
 
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo3", ImmutableList.of(intType), false, new ReflectionTypeSolver());
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo3", ImmutableList.of(intType), false);
         assertEquals(true, ref.isSolved());
         assertEquals("A", ref.getCorrespondingDeclaration().declaringType().getName());
         assertEquals(1, ref.getCorrespondingDeclaration().getNumberOfParams());
     }
 
     @Test
-    public void solveMethodWithMoreSpecializedParameter() {
+    void solveMethodWithMoreSpecializedParameter() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
 
         ResolvedType stringType = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
 
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo4", ImmutableList.of(stringType), false, new ReflectionTypeSolver());
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo4", ImmutableList.of(stringType), false);
         assertEquals(true, ref.isSolved());
         assertEquals("A", ref.getCorrespondingDeclaration().declaringType().getName());
         assertEquals(1, ref.getCorrespondingDeclaration().getNumberOfParams());
     }
 
-    @Test(expected = MethodAmbiguityException.class)
-    public void solveMethodWithAmbiguosCall() {
-        CompilationUnit cu = parseSample("ClassWithMethods");
+    @Test
+    void solveMethodWithAmbiguosCall() {
+        assertThrows(MethodAmbiguityException.class, () -> {
+            CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
         Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
-
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo5", ImmutableList.of(NullType.INSTANCE), false, new ReflectionTypeSolver());
-    }
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("foo5", ImmutableList.of(NullType.INSTANCE), false);
+    });
+                
+}
 
     @Test
-    public void solveMethodAsUsageSimpleCase() {
+    void solveMethodAsUsageSimpleCase() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
-        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
+        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration,
+                                                                 new ReflectionTypeSolver());
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo0", ImmutableList.of(), new ReflectionTypeSolver());
+        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo0", ImmutableList.of());
         assertEquals(true, ref.isPresent());
         assertEquals("A", ref.get().declaringType().getName());
         assertEquals(0, ref.get().getNoParams());
     }
 
     @Test
-    public void solveMethodAsUsageOverrideCase() {
+    void solveMethodAsUsageOverrideCase() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
-        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
+        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration,
+                                                                 new ReflectionTypeSolver());
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo1", ImmutableList.of(), new ReflectionTypeSolver());
+        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo1", ImmutableList.of());
         assertEquals(true, ref.isPresent());
         assertEquals("A", ref.get().declaringType().getName());
         assertEquals(0, ref.get().getNoParams());
     }
 
     @Test
-    public void solveMethodAsUsageInheritedCase() {
+    void solveMethodAsUsageInheritedCase() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
-        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
+        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration,
+                                                                 new ReflectionTypeSolver());
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo2", ImmutableList.of(), new ReflectionTypeSolver());
+        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo2", ImmutableList.of());
         assertEquals(true, ref.isPresent());
         assertEquals("Super", ref.get().declaringType().getName());
         assertEquals(0, ref.get().getNoParams());
     }
 
     @Test
-    public void solveMethodAsUsageWithPrimitiveParameters() {
+    void solveMethodAsUsageWithPrimitiveParameters() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
-        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
+        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration,
+                                                                 new ReflectionTypeSolver());
 
         ResolvedType intType = ResolvedPrimitiveType.INT;
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo3", ImmutableList.of(intType), new ReflectionTypeSolver());
+        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo3", ImmutableList.of(intType));
         assertEquals(true, ref.isPresent());
         assertEquals("A", ref.get().declaringType().getName());
         assertEquals(1, ref.get().getNoParams());
     }
 
     @Test
-    public void solveMethodAsUsageWithMoreSpecializedParameter() {
+    void solveMethodAsUsageWithMoreSpecializedParameter() {
         CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
-        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
+        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration,
+                                                                 new ReflectionTypeSolver());
 
         ResolvedType stringType = new ReferenceTypeImpl(new ReflectionClassDeclaration(String.class, typeSolver), typeSolver);
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo4", ImmutableList.of(stringType), new ReflectionTypeSolver());
+        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo4", ImmutableList.of(stringType));
         assertEquals(true, ref.isPresent());
         assertEquals("A", ref.get().declaringType().getName());
         assertEquals(1, ref.get().getNoParams());
     }
 
-    @Test(expected = MethodAmbiguityException.class)
-    public void solveMethodAsUsageWithAmbiguosCall() {
-        CompilationUnit cu = parseSample("ClassWithMethods");
+    @Test
+    void solveMethodAsUsageWithAmbiguosCall() {
+        assertThrows(MethodAmbiguityException.class, () -> {
+            CompilationUnit cu = parseSample("ClassWithMethods");
         ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
-        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
-
-        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo5", ImmutableList.of(NullType.INSTANCE), new ReflectionTypeSolver());
-    }
+        Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, new ReflectionTypeSolver());
+        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo5", ImmutableList.of(NullType.INSTANCE));
+    });
+                
 }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/CompilationUnitContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/CompilationUnitContextResolutionTest.java
index c079e59..0787838 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/CompilationUnitContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/CompilationUnitContextResolutionTest.java
@@ -36,31 +36,31 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
 import com.google.common.collect.ImmutableList;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
 import java.util.Optional;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 /**
  * @author Federico Tomassetti
- */
-public class CompilationUnitContextResolutionTest extends AbstractResolutionTest {
+a */
+class CompilationUnitContextResolutionTest extends AbstractResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
     }
 
     @Test
-    public void getParent() {
+    void getParent() {
         CompilationUnit cu = parseSample("ClassWithTypeVariables");
         Context context = new CompilationUnitContext(cu, typeSolver);
 
@@ -68,13 +68,13 @@
     }
 
     @Test
-    public void solveExistingGenericType() {
+    void solveExistingGenericType() {
         CompilationUnit cu = parseSample("ClassWithTypeVariables");
         Context context = new CompilationUnitContext(cu, typeSolver);
 
-        Optional<ResolvedType> a = context.solveGenericType("A", new MemoryTypeSolver());
-        Optional<ResolvedType> b = context.solveGenericType("B", new MemoryTypeSolver());
-        Optional<ResolvedType> c = context.solveGenericType("C", new MemoryTypeSolver());
+        Optional<ResolvedType> a = context.solveGenericType("A");
+        Optional<ResolvedType> b = context.solveGenericType("B");
+        Optional<ResolvedType> c = context.solveGenericType("C");
 
         assertEquals(false, a.isPresent());
         assertEquals(false, b.isPresent());
@@ -82,132 +82,137 @@
     }
 
     @Test
-    public void solveUnexistingGenericType() {
+    void solveUnexistingGenericType() {
         CompilationUnit cu = parseSample("ClassWithTypeVariables");
         Context context = new CompilationUnitContext(cu, typeSolver);
 
-        Optional<ResolvedType> d = context.solveGenericType("D", new MemoryTypeSolver());
+        Optional<ResolvedType> d = context.solveGenericType("D");
 
         assertEquals(false, d.isPresent());
     }
 
     @Test
-    public void solveSymbolReferringToStaticallyImportedValue() throws ParseException, IOException {
+    void solveSymbolReferringToStaticallyImportedValue() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitSymbols");
-        Context context = new CompilationUnitContext(cu, typeSolver);
 
         CombinedTypeSolver typeSolver = new CombinedTypeSolver();
         typeSolver.add(new ReflectionTypeSolver());
         typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("out", typeSolver);
+
+        Context context = new CompilationUnitContext(cu, typeSolver);
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("out");
+
         assertEquals(true, ref.isSolved());
         assertEquals("java.io.PrintStream", ref.getCorrespondingDeclaration().getType().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void solveSymbolReferringToStaticallyImportedUsingAsteriskValue() throws ParseException, IOException {
+    void solveSymbolReferringToStaticallyImportedUsingAsteriskValue() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitSymbols");
-        Context context = new CompilationUnitContext(cu, typeSolver);
 
         CombinedTypeSolver typeSolver = new CombinedTypeSolver();
         typeSolver.add(new ReflectionTypeSolver());
         typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("err", typeSolver);
+
+        Context context = new CompilationUnitContext(cu, typeSolver);
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("err");
         assertEquals(true, ref.isSolved());
         assertEquals("java.io.PrintStream", ref.getCorrespondingDeclaration().getType().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void solveSymbolReferringToStaticField() throws ParseException, IOException {
+    void solveSymbolReferringToStaticField() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitSymbols");
-        Context context = new CompilationUnitContext(cu, typeSolver);
+        Context context = new CompilationUnitContext(cu, new ReflectionTypeSolver());
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("java.lang.System.out", new ReflectionTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("java.lang.System.out");
         assertEquals(true, ref.isSolved());
         assertEquals("java.io.PrintStream", ref.getCorrespondingDeclaration().getType().asReferenceType().getQualifiedName());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToStaticallyImportedValue() throws ParseException, IOException {
+    void solveSymbolAsValueReferringToStaticallyImportedValue() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitSymbols");
         Context context = new CompilationUnitContext(cu, typeSolver);
 
         CombinedTypeSolver typeSolver = new CombinedTypeSolver();
         typeSolver.add(new ReflectionTypeSolver());
         typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
-        Optional<Value> ref = context.solveSymbolAsValue("out", typeSolver);
+        Optional<Value> ref = context.solveSymbolAsValue("out");
         assertEquals(true, ref.isPresent());
         assertEquals("java.io.PrintStream", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToStaticallyImportedUsingAsteriskValue() throws ParseException, IOException {
+    void solveSymbolAsValueReferringToStaticallyImportedUsingAsteriskValue() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitSymbols");
         Context context = new CompilationUnitContext(cu, typeSolver);
 
         CombinedTypeSolver typeSolver = new CombinedTypeSolver();
         typeSolver.add(new ReflectionTypeSolver());
         typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
-        Optional<Value> ref = context.solveSymbolAsValue("err", typeSolver);
+        Optional<Value> ref = context.solveSymbolAsValue("err");
         assertEquals(true, ref.isPresent());
         assertEquals("java.io.PrintStream", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToStaticField() throws ParseException, IOException {
+    void solveSymbolAsValueReferringToStaticField() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitSymbols");
-        Context context = new CompilationUnitContext(cu, typeSolver);
+        Context context = new CompilationUnitContext(cu, new ReflectionTypeSolver());
 
-        Optional<Value> ref = context.solveSymbolAsValue("java.lang.System.out", new ReflectionTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("java.lang.System.out");
         assertEquals(true, ref.isPresent());
         assertEquals("java.io.PrintStream", ref.get().getType().describe());
     }
 
     @Test
-    public void solveTypeInSamePackage() {
+    void solveTypeInSamePackage() {
         CompilationUnit cu = parseSample("CompilationUnitWithImports");
-        Context context = new CompilationUnitContext(cu, typeSolver);
 
         ResolvedReferenceTypeDeclaration otherClass = mock(ResolvedReferenceTypeDeclaration.class);
         when(otherClass.getQualifiedName()).thenReturn("com.foo.OtherClassInSamePackage");
         MemoryTypeSolver memoryTypeSolver = new MemoryTypeSolver();
         memoryTypeSolver.addDeclaration("com.foo.OtherClassInSamePackage", otherClass);
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("OtherClassInSamePackage", memoryTypeSolver);
+        Context context = new CompilationUnitContext(cu, memoryTypeSolver);
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("OtherClassInSamePackage");
+
         assertEquals(true, ref.isSolved());
         assertEquals("com.foo.OtherClassInSamePackage", ref.getCorrespondingDeclaration().getQualifiedName());
     }
 
     @Test
-    public void solveTypeImported() throws ParseException, IOException {
+    void solveTypeImported() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitWithImports");
-        Context context = new CompilationUnitContext(cu, typeSolver);
+        Context context = new CompilationUnitContext(cu, new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Assert", new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("Assert");
         assertEquals(true, ref.isSolved());
         assertEquals("org.junit.Assert", ref.getCorrespondingDeclaration().getQualifiedName());
     }
 
     @Test
-    public void solveTypeNotImported() throws ParseException, IOException {
+    void solveTypeNotImported() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitWithImports");
-        Context context = new CompilationUnitContext(cu, typeSolver);
+        Context context = new CompilationUnitContext(cu, new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("org.junit.Assume", new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("org.junit.Assume");
         assertEquals(true, ref.isSolved());
         assertEquals("org.junit.Assume", ref.getCorrespondingDeclaration().getQualifiedName());
     }
 
     @Test
-    public void solveMethodStaticallyImportedWithAsterisk() throws ParseException, IOException {
+    void solveMethodStaticallyImportedWithAsterisk() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitWithImports");
-        Context context = new CompilationUnitContext(cu, typeSolver);
 
         CombinedTypeSolver typeSolver = new CombinedTypeSolver();
         typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
         typeSolver.add(new ReflectionTypeSolver());
 
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("assertFalse", ImmutableList.of(ResolvedPrimitiveType.BOOLEAN), false, typeSolver);
+        Context context = new CompilationUnitContext(cu, typeSolver);
+
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("assertFalse", ImmutableList.of(ResolvedPrimitiveType.BOOLEAN), false);
         assertEquals(true, ref.isSolved());
         assertEquals("assertFalse", ref.getCorrespondingDeclaration().getName());
         assertEquals(1, ref.getCorrespondingDeclaration().getNumberOfParams());
@@ -216,15 +221,16 @@
     }
 
     @Test
-    public void solveMethodStaticallyImportedWithoutAsterisk() throws ParseException, IOException {
+    void solveMethodStaticallyImportedWithoutAsterisk() throws ParseException, IOException {
         CompilationUnit cu = parseSample("CompilationUnitSymbols");
-        Context context = new CompilationUnitContext(cu, typeSolver);
 
         CombinedTypeSolver typeSolver = new CombinedTypeSolver();
         typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/junit-4.8.1.jar")));
         typeSolver.add(new ReflectionTypeSolver());
 
-        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("assertEquals", ImmutableList.of(NullType.INSTANCE, NullType.INSTANCE), false, typeSolver);
+        Context context = new CompilationUnitContext(cu, typeSolver);
+
+        SymbolReference<ResolvedMethodDeclaration> ref = context.solveMethod("assertEquals", ImmutableList.of(NullType.INSTANCE, NullType.INSTANCE), false);
         assertEquals(true, ref.isSolved());
         assertEquals("assertEquals", ref.getCorrespondingDeclaration().getName());
         assertEquals(2, ref.getCorrespondingDeclaration().getNumberOfParams());
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/EnumDeclarationContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/EnumDeclarationContextResolutionTest.java
index 93af30e..0f7bdbb 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/EnumDeclarationContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/EnumDeclarationContextResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution.javaparser.contexts;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
@@ -28,87 +27,87 @@
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Optional;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * @author Federico Tomassetti
  */
-public class EnumDeclarationContextResolutionTest extends AbstractResolutionTest {
+class EnumDeclarationContextResolutionTest extends AbstractResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
     }
 
     @Test
-    public void solveSymbolReferringToDeclaredInstanceField() {
+    void solveSymbolReferringToDeclaredInstanceField() {
         CompilationUnit cu = parseSample("AnEnum");
         com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = Navigator.demandEnum(cu, "MyEnum");
         Context context = new EnumDeclarationContext(enumDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("i", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("i");
         assertEquals(true, ref.isSolved());
         assertEquals("int", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolReferringToDeclaredStaticField() {
+    void solveSymbolReferringToDeclaredStaticField() {
         CompilationUnit cu = parseSample("AnEnum");
         com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = Navigator.demandEnum(cu, "MyEnum");
         Context context = new EnumDeclarationContext(enumDeclaration, typeSolver);
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("j", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("j");
         assertEquals(true, ref.isSolved());
         assertEquals("long", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolReferringToValue() {
+    void solveSymbolReferringToValue() {
         CompilationUnit cu = parseSample("AnEnum");
         com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = Navigator.demandEnum(cu, "MyEnum");
-        Context context = new EnumDeclarationContext(enumDeclaration, typeSolver);
+        Context context = new EnumDeclarationContext(enumDeclaration, new MemoryTypeSolver());
 
-        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("E1", new MemoryTypeSolver());
+        SymbolReference<? extends ResolvedValueDeclaration> ref = context.solveSymbol("E1");
         assertEquals(true, ref.isSolved());
         assertEquals("MyEnum", ref.getCorrespondingDeclaration().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToDeclaredInstanceField() {
+    void solveSymbolAsValueReferringToDeclaredInstanceField() {
         CompilationUnit cu = parseSample("AnEnum");
         com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = Navigator.demandEnum(cu, "MyEnum");
         Context context = new EnumDeclarationContext(enumDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("i", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("i");
         assertEquals(true, ref.isPresent());
         assertEquals("int", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToDeclaredStaticField() {
+    void solveSymbolAsValueReferringToDeclaredStaticField() {
         CompilationUnit cu = parseSample("AnEnum");
         com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = Navigator.demandEnum(cu, "MyEnum");
         Context context = new EnumDeclarationContext(enumDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("j", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("j");
         assertEquals(true, ref.isPresent());
         assertEquals("long", ref.get().getType().describe());
     }
 
     @Test
-    public void solveSymbolAsValueReferringToValue() {
+    void solveSymbolAsValueReferringToValue() {
         CompilationUnit cu = parseSample("AnEnum");
         com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = Navigator.demandEnum(cu, "MyEnum");
         Context context = new EnumDeclarationContext(enumDeclaration, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("E1", new MemoryTypeSolver());
+        Optional<Value> ref = context.solveSymbolAsValue("E1");
         assertEquals(true, ref.isPresent());
         assertEquals("MyEnum", ref.get().getType().describe());
     }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/FieldAccessContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/FieldAccessContextResolutionTest.java
index b13737e..9679e93 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/FieldAccessContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/FieldAccessContextResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution.javaparser.contexts;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.MethodCallExpr;
@@ -26,17 +25,17 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * @author Malte Langkabel
  */
-public class FieldAccessContextResolutionTest extends AbstractResolutionTest {
+class FieldAccessContextResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void solveMethodCallInFieldAccessContext() {
+    void solveMethodCallInFieldAccessContext() {
         CompilationUnit cu = parseSample("MethodCalls");
 
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/LambdaExprContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/LambdaExprContextResolutionTest.java
index 63e513c..ac9cf34 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/LambdaExprContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/LambdaExprContextResolutionTest.java
@@ -31,29 +31,31 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Optional;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * @author Malte Langkabel
  */
-public class LambdaExprContextResolutionTest extends AbstractResolutionTest {
+class LambdaExprContextResolutionTest extends AbstractResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
     }
 
     @Test
-    public void solveParameterOfLambdaInMethodCallExpr() {
+    void solveParameterOfLambdaInMethodCallExpr() {
         CompilationUnit cu = parseSample("Lambda");
 
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
@@ -64,33 +66,33 @@
 
         Context context = new LambdaExprContext(lambdaExpr, typeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("p", typeSolver);
+        Optional<Value> ref = context.solveSymbolAsValue("p");
         assertTrue(ref.isPresent());
         assertEquals("? super java.lang.String", ref.get().getType().describe());
     }
 
     @Test
-    public void solveParameterOfLambdaInFieldDecl() {
+    void solveParameterOfLambdaInFieldDecl() {
         CompilationUnit cu = parseSample("Lambda");
 
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
         VariableDeclarator field = Navigator.demandField(clazz, "functional");
         LambdaExpr lambdaExpr = (LambdaExpr) field.getInitializer().get();
 
-        File src = new File("src/test/resources");
+        Path src = Paths.get("src/test/resources");
         CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
         combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(src)));
+        combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(src), new LeanParserConfiguration()));
 
         Context context = new LambdaExprContext(lambdaExpr, combinedTypeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("p", typeSolver);
+        Optional<Value> ref = context.solveSymbolAsValue("p");
         assertTrue(ref.isPresent());
         assertEquals("java.lang.String", ref.get().getType().describe());
     }
 
     @Test
-    public void solveParameterOfLambdaInVarDecl() {
+    void solveParameterOfLambdaInVarDecl() {
         CompilationUnit cu = parseSample("Lambda");
 
         com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "Agenda");
@@ -98,14 +100,14 @@
         VariableDeclarator varDecl = Navigator.demandVariableDeclaration(method, "a").get();
         LambdaExpr lambdaExpr = (LambdaExpr) varDecl.getInitializer().get();
 
-        File src = adaptPath(new File("src/test/resources"));
+        Path src = adaptPath("src/test/resources");
         CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
         combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(src));
+        combinedTypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
 
         Context context = new LambdaExprContext(lambdaExpr, combinedTypeSolver);
 
-        Optional<Value> ref = context.solveSymbolAsValue("p", typeSolver);
+        Optional<Value> ref = context.solveSymbolAsValue("p");
         assertTrue(ref.isPresent());
         assertEquals("java.lang.String", ref.get().getType().describe());
     }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodCallExprContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodCallExprContextResolutionTest.java
index 7fdaf73..38035f5 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodCallExprContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodCallExprContextResolutionTest.java
@@ -16,13 +16,18 @@
 
 package com.github.javaparser.symbolsolver.resolution.javaparser.contexts;
 
-import com.github.javaparser.ParseException;
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.MethodCallExpr;
 import com.github.javaparser.resolution.MethodUsage;
 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
 import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.resolution.types.ResolvedVoidType;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
 import com.github.javaparser.symbolsolver.core.resolution.Context;
 import com.github.javaparser.symbolsolver.javaparser.Navigator;
 import com.github.javaparser.symbolsolver.javaparsermodel.contexts.MethodCallExprContext;
@@ -31,96 +36,111 @@
 import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * @author Malte Langkabel
  */
-public class MethodCallExprContextResolutionTest extends AbstractResolutionTest {
-    private MethodCallExpr getMethodCallExpr(String methodName, String callingMethodName) {
-        CompilationUnit cu = parseSample("MethodCalls");
+class MethodCallExprContextResolutionTest extends AbstractResolutionTest {
+	private MethodCallExpr getMethodCallExpr(String methodName, String callingMethodName) {
+		CompilationUnit cu = parseSample("MethodCalls");
 
-        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
-        MethodDeclaration method = Navigator.demandMethod(clazz, methodName);
-        return Navigator.findMethodCall(method, callingMethodName).get();
-    }
+		com.github.javaparser.ast.body.ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MethodCalls");
+		MethodDeclaration method = Navigator.demandMethod(clazz, methodName);
+		return Navigator.findMethodCall(method, callingMethodName).get();
+	}
 
-    private CombinedTypeSolver createTypeSolver() {
-        File src = adaptPath(new File("src/test/resources"));
-        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
-        combinedTypeSolver.add(new ReflectionTypeSolver());
-        combinedTypeSolver.add(new JavaParserTypeSolver(src));
-        return combinedTypeSolver;
-    }
+	private CombinedTypeSolver createTypeSolver() {
+		Path src = adaptPath("src/test/resources");
+		CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
+		combinedTypeSolver.add(new ReflectionTypeSolver());
+		combinedTypeSolver.add(new JavaParserTypeSolver(src, new LeanParserConfiguration()));
+		return combinedTypeSolver;
+	}
 
-    @Test
-    public void solveNestedMethodCallExprContextWithoutScope() {
-        MethodCallExpr methodCallExpr = getMethodCallExpr("bar1", "foo");
-        CombinedTypeSolver typeSolver = createTypeSolver();
+	@Test
+	void solveNestedMethodCallExprContextWithoutScope() {
+		MethodCallExpr methodCallExpr = getMethodCallExpr("bar1", "foo");
+		CombinedTypeSolver typeSolver = createTypeSolver();
 
-        Context context = new MethodCallExprContext(methodCallExpr, typeSolver);
+		Context context = new MethodCallExprContext(methodCallExpr, typeSolver);
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage("foo", Collections.emptyList(), typeSolver);
-        assertTrue(ref.isPresent());
-        assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
-    }
+		Optional<MethodUsage> ref = context.solveMethodAsUsage("foo", Collections.emptyList());
+		assertTrue(ref.isPresent());
+		assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
+	}
 
-    @Test
-    public void solveGenericMethodCallMustUseProvidedTypeArgs() {
-        assertCanSolveGenericMethodCallMustUseProvidedTypeArgs("genericMethod0");
-    }
+	@Test
+	void solveGenericMethodCallMustUseProvidedTypeArgs() {
+		assertCanSolveGenericMethodCallMustUseProvidedTypeArgs("genericMethod0");
+	}
 
-    @Test
-    public void solveStaticGenericMethodCallMustUseProvidedTypeArgs() {
-        assertCanSolveGenericMethodCallMustUseProvidedTypeArgs("staticGenericMethod0");
-    }
+	@Test
+	void solveStaticGenericMethodCallMustUseProvidedTypeArgs() {
+		assertCanSolveGenericMethodCallMustUseProvidedTypeArgs("staticGenericMethod0");
+	}
 
-    private void assertCanSolveGenericMethodCallMustUseProvidedTypeArgs(String callMethodName) {
-        MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", callMethodName);
-        CombinedTypeSolver typeSolver = createTypeSolver();
+	private void assertCanSolveGenericMethodCallMustUseProvidedTypeArgs(String callMethodName) {
+		MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", callMethodName);
+		CombinedTypeSolver typeSolver = createTypeSolver();
 
-        MethodCallExprContext context = new MethodCallExprContext(methodCallExpr, typeSolver);
+		MethodCallExprContext context = new MethodCallExprContext(methodCallExpr, typeSolver);
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage(callMethodName, Collections.emptyList(), typeSolver);
-        assertTrue(ref.isPresent());
-        assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
-        assertEquals(Collections.singletonList("java.lang.Integer"), ref.get().typeParametersMap().getTypes().stream().map(ty -> ty.asReferenceType().describe()).collect(Collectors.toList()));
-    }
+		Optional<MethodUsage> ref = context.solveMethodAsUsage(callMethodName, Collections.emptyList());
+		assertTrue(ref.isPresent());
+		assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
+		assertEquals(Collections.singletonList("java.lang.Integer"), ref.get().typeParametersMap().getTypes().stream()
+				.map(ty -> ty.asReferenceType().describe()).collect(Collectors.toList()));
+	}
 
-    @Test
-    public void solveGenericMethodCallCanInferFromArguments() {
-        assertCanSolveGenericMethodCallCanInferFromArguments("genericMethod1");
-    }
+	@Test
+	void solveGenericMethodCallCanInferFromArguments() {
+		assertCanSolveGenericMethodCallCanInferFromArguments("genericMethod1");
+	}
 
-    @Test
-    public void solveStaticGenericMethodCallCanInferFromArguments() {
-        assertCanSolveGenericMethodCallCanInferFromArguments("staticGenericMethod1");
-    }
+	@Test
+	void solveStaticGenericMethodCallCanInferFromArguments() {
+		assertCanSolveGenericMethodCallCanInferFromArguments("staticGenericMethod1");
+	}
 
-    private void assertCanSolveGenericMethodCallCanInferFromArguments(String callMethodName) {
-        MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", callMethodName);
-        CombinedTypeSolver typeSolver = createTypeSolver();
+	private void assertCanSolveGenericMethodCallCanInferFromArguments(String callMethodName) {
+		MethodCallExpr methodCallExpr = getMethodCallExpr("genericMethodTest", callMethodName);
+		CombinedTypeSolver typeSolver = createTypeSolver();
 
-        MethodCallExprContext context = new MethodCallExprContext(methodCallExpr, typeSolver);
+		MethodCallExprContext context = new MethodCallExprContext(methodCallExpr, typeSolver);
 
-        ResolvedReferenceTypeDeclaration stringType = typeSolver.solveType("java.lang.String");
+		ResolvedReferenceTypeDeclaration stringType = typeSolver.solveType("java.lang.String");
 
-        List<ResolvedType> argumentsTypes = new ArrayList<>();
-        argumentsTypes.add(new ReferenceTypeImpl(stringType, typeSolver));
+		List<ResolvedType> argumentsTypes = new ArrayList<>();
+		argumentsTypes.add(new ReferenceTypeImpl(stringType, typeSolver));
 
-        Optional<MethodUsage> ref = context.solveMethodAsUsage(callMethodName, argumentsTypes, typeSolver);
-        assertTrue(ref.isPresent());
-        assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
-        assertEquals(Collections.singletonList("java.lang.String"), ref.get().typeParametersMap().getTypes().stream().map(ty -> ty.asReferenceType().describe()).collect(Collectors.toList()));
-    }
+		Optional<MethodUsage> ref = context.solveMethodAsUsage(callMethodName, argumentsTypes);
+		assertTrue(ref.isPresent());
+		assertEquals("MethodCalls", ref.get().declaringType().getQualifiedName());
+		assertEquals(Collections.singletonList("java.lang.String"), ref.get().typeParametersMap().getTypes().stream()
+				.map(ty -> ty.asReferenceType().describe()).collect(Collectors.toList()));
+	}
+
+	@Test
+	public void test() {
+		ParserConfiguration config = new ParserConfiguration()
+				.setSymbolResolver(new JavaSymbolSolver(createTypeSolver()));
+		StaticJavaParser.setConfiguration(config);
+		CompilationUnit cu = parseSample("Issue2258");
+		List<MethodCallExpr> expressions = cu.getChildNodesByType(MethodCallExpr.class);
+		assertTrue(expressions.size() == 2);
+		ResolvedType r = expressions.get(1).calculateResolvedType();
+		assertTrue(ResolvedVoidType.class.isAssignableFrom(r.getClass()));
+	}
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodContextResolutionTest.java
index 17d9780..93b3d04 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodContextResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/contexts/MethodContextResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution.javaparser.contexts;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
@@ -29,31 +28,31 @@
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * @author Malte Langkabel
  */
-public class MethodContextResolutionTest extends AbstractResolutionTest {
+class MethodContextResolutionTest extends AbstractResolutionTest {
 
     private TypeSolver typeSolver;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         typeSolver = new ReflectionTypeSolver();
     }
 
     @Test
-    public void solveTypeRefToLocalClass() {
+    void solveTypeRefToLocalClass() {
         CompilationUnit cu = parseSample("MethodWithTypes");
         ClassOrInterfaceDeclaration cd = Navigator.demandClass(cu, "Main");
         MethodDeclaration md = Navigator.demandMethod(cd, "methodWithLocalTypes");
-        Context context = new MethodContext(md, typeSolver);
+        Context context = new MethodContext(md, new MemoryTypeSolver());
 
-        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("LocalClass", new MemoryTypeSolver());
+        SymbolReference<ResolvedTypeDeclaration> ref = context.solveType("LocalClass");
         assertEquals(true, ref.isSolved());
     }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/declarations/JavaParserTypeParameterResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/declarations/JavaParserTypeParameterResolutionTest.java
index c72e772..35719dc 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/declarations/JavaParserTypeParameterResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/javaparser/declarations/JavaParserTypeParameterResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution.javaparser.declarations;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
@@ -30,12 +29,12 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class JavaParserTypeParameterResolutionTest extends AbstractResolutionTest {
+class JavaParserTypeParameterResolutionTest extends AbstractResolutionTest {
 
     private void testGenericArguments(String containingMethodName) {
         CompilationUnit cu = parseSample("GenericMethodArguments");
@@ -49,17 +48,17 @@
     }
 
     @Test
-    public void genericMethodWithGenericClassBasedArgument() {
+    void genericMethodWithGenericClassBasedArgument() {
         testGenericArguments("useCase1");
     }
 
     @Test
-    public void genericMethodWithGenericClassArgument() {
+    void genericMethodWithGenericClassArgument() {
         testGenericArguments("useCase2");
     }
 
     @Test
-    public void declaredOnMethodPositiveCase() {
+    void declaredOnMethodPositiveCase() {
         CompilationUnit cu = parseSample("MethodTypeParameter");
         TypeSolver typeSolver = new ReflectionTypeSolver();
         JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
@@ -76,7 +75,7 @@
     }
 
     @Test
-    public void declaredOnMethodNegativeCase() {
+    void declaredOnMethodNegativeCase() {
         CompilationUnit cu = parseSample("ClassTypeParameter");
         TypeSolver typeSolver = new ReflectionTypeSolver();
         JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver);
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/AbstractNameLogicTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/AbstractNameLogicTest.java
new file mode 100644
index 0000000..60a6fee
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/AbstractNameLogicTest.java
@@ -0,0 +1,84 @@
+package com.github.javaparser.symbolsolver.resolution.naming;
+
+import com.github.javaparser.*;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public abstract class AbstractNameLogicTest extends AbstractResolutionTest {
+
+    protected Node getNameInCodeTollerant(String code, String name, ParseStart parseStart) {
+        return getNameInCode(code, name, parseStart, true, Optional.empty());
+    }
+
+    protected Node getNameInCodeTollerant(String code, String name, ParseStart parseStart, TypeSolver typeSolver) {
+        return getNameInCode(code, name, parseStart, true, Optional.of(typeSolver));
+    }
+
+    protected Node getNameInCode(String code, String name, ParseStart parseStart) {
+        return getNameInCode(code, name, parseStart, false, Optional.empty());
+    }
+
+    protected <N extends Node> N parse(String code, ParseStart<N> parseStart) {
+        return parse(code, parseStart, Optional.empty());
+    }
+
+    protected <N extends Node> N parse(String code, ParseStart<N> parseStart, Optional<TypeSolver> typeSolver) {
+        ParserConfiguration parserConfiguration = new ParserConfiguration();
+        parserConfiguration.setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_10);
+        if (typeSolver.isPresent()) {
+            parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver.get()));
+        }
+        ParseResult<N> parseResult = new JavaParser(parserConfiguration).parse(parseStart, new StringProvider(code));
+        if (!parseResult.isSuccessful()) {
+            parseResult.getProblems().forEach(p -> System.out.println("ERR: " + p));
+        }
+        assertTrue(parseResult.isSuccessful());
+        N root = parseResult.getResult().get();
+        return root;
+    }
+
+    private Node getNameInCode(String code, String name, ParseStart parseStart, boolean tollerant,
+                               Optional<TypeSolver> typeSolver) {
+        Node root = parse(code, parseStart, typeSolver);
+        List<Node> allNames = root.findAll(Node.class).stream()
+                .filter(NameLogic::isAName)
+                .collect(Collectors.toList());
+        List<Node> matchingNames = allNames.stream()
+                .filter(n -> NameLogic.nameAsString(n).equals(name))
+                .collect(Collectors.toList());
+        // In case of one name being contained in other as is, we remove it
+        for (int i=0;i<matchingNames.size();i++) {
+            Node container = matchingNames.get(i);
+            for (int j=i+1;j<matchingNames.size();j++) {
+                Node contained = matchingNames.get(j);
+                if (contained.getParentNode().isPresent() && contained.getParentNode().get() == container
+                        && NameLogic.nameAsString(contained).equals(NameLogic.nameAsString(container))) {
+                    matchingNames.remove(j);
+                    j--;
+                }
+            }
+        }
+
+        if (matchingNames.size() == 0) {
+            throw new IllegalArgumentException("Not found. Names found: " + String.join(", ",
+                    allNames.stream().map(NameLogic::nameAsString).collect(Collectors.toList())));
+        } else if (matchingNames.size() > 1) {
+            if (tollerant) {
+                return matchingNames.get(matchingNames.size() - 1);
+            } else {
+                throw new IllegalArgumentException("Ambiguous: there are several matching.");
+            }
+        } else {
+            return matchingNames.get(0);
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicDisambiguationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicDisambiguationTest.java
new file mode 100644
index 0000000..943ef8d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicDisambiguationTest.java
@@ -0,0 +1,356 @@
+package com.github.javaparser.symbolsolver.resolution.naming;
+
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class NameLogicDisambiguationTest extends AbstractNameLogicTest {
+
+    private void assertNameInCodeIsDisambiguited(String code, String name,
+                                                 NameCategory syntacticClassification,
+                                                 NameCategory nameCategory,
+                                                 ParseStart parseStart, TypeSolver typeSolver) {
+        Node nameNode = getNameInCodeTollerant(code, name, parseStart, typeSolver);
+        assertEquals(syntacticClassification, NameLogic.syntacticClassificationAccordingToContext(nameNode));
+        assertEquals(nameCategory, NameLogic.classifyReference(nameNode, typeSolver));
+    }
+
+    @Test
+    void ambiguousNameToLocalVar() {
+        assertNameInCodeIsDisambiguited("class A { void foo() {\n" +
+                "SomeClass a; a.aField;" + "\n" +
+                "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new ReflectionTypeSolver());
+    }
+
+    @Test
+    void ambiguousNameToLocalVarInAnnidatedBlocks() {
+        assertNameInCodeIsDisambiguited("class A { void foo() {{\n" +
+                        "SomeClass a; {{a.aField;}}}" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new ReflectionTypeSolver());
+    }
+
+    @Test
+    void ambiguousNameToLocalVarFromOldFor() {
+        assertNameInCodeIsDisambiguited("class A { void foo() {\n" +
+                        "for (SomeClass a=null;true;){ a.aField; }" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new ReflectionTypeSolver());
+    }
+
+    @Test
+    void ambiguousNameToLocalVarFromNewFor() {
+        assertNameInCodeIsDisambiguited("class A { void foo() {\n" +
+                        "for (SomeClass a : null){ a.aField; }" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new ReflectionTypeSolver());
+    }
+
+    @Test
+    void ambiguousNameToLocalVarFromTryWithResource() {
+        assertNameInCodeIsDisambiguited("class A { void foo() {\n" +
+                        "try (SomeClass a = null){ a.aField; }" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new ReflectionTypeSolver());
+    }
+
+    @Test
+    void ambiguousNameToMethodParameter() {
+        assertNameInCodeIsDisambiguited("class A { void foo(SomeClass a) {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new ReflectionTypeSolver());
+    }
+
+    @Test
+    void ambiguousNameToCatchParameter() {
+        assertNameInCodeIsDisambiguited("class A { void foo() {\n" +
+                        "try { } catch (SomeClass a) { a.aField; }" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new ReflectionTypeSolver());
+    }
+
+    @Test
+    void ambiguousNameToInstanceFieldDeclared() {
+        assertNameInCodeIsDisambiguited("class A { SomeClass a; void foo() {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver()));
+    }
+
+    @Test
+    void ambiguousNameToStaticFieldDeclared() {
+        assertNameInCodeIsDisambiguited("class A { static SomeClass a; void foo() {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver()));
+    }
+
+    @Test
+    void ambiguousNameToInstanceFieldInherited() {
+        assertNameInCodeIsDisambiguited("class A { SomeClass a; } class B extends A { void foo() {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver()));
+    }
+
+    @Test
+    void ambiguousNameToStaticFieldInherited() {
+        assertNameInCodeIsDisambiguited("class A { static SomeClass a; } class B extends A {  void foo() {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver()));
+    }
+
+    // Otherwise, if a field of that name is declared in the compilation unit (§7.3) containing the Identifier by a
+    // single-static-import declaration (§7.5.3), or by a static-import-on-demand declaration (§7.5.4) then the
+    // AmbiguousName is reclassified as an ExpressionName.
+
+    @Test
+    void ambiguousNameToSingleStaticImportDeclaration() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        ResolvedFieldDeclaration mockedFieldA = mock(ResolvedFieldDeclaration.class);
+        when(mockedFieldA.isStatic()).thenReturn(true);
+        when(mockedFieldA.getName()).thenReturn("a");
+        when(mockedC.getAllFields()).thenReturn(Arrays.asList(mockedFieldA));
+        typeSolver.addDeclaration("foo.bar.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("import static foo.bar.C.a; class B {  void foo() {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    @Test
+    void ambiguousNameToStaticImportOnDemandDeclaration() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        ResolvedFieldDeclaration mockedFieldA = mock(ResolvedFieldDeclaration.class);
+        when(mockedFieldA.isStatic()).thenReturn(true);
+        when(mockedFieldA.getName()).thenReturn("a");
+        when(mockedC.getAllFields()).thenReturn(Arrays.asList(mockedFieldA));
+        typeSolver.addDeclaration("foo.bar.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("import static foo.bar.C.*; class B {  void foo() {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    @Test
+    void ambiguousNameDefaultToPackageName() {
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.aField;" + "\n" +
+                        "} }", "a", NameCategory.AMBIGUOUS_NAME, NameCategory.PACKAGE_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver()));
+    }
+
+    // If the AmbiguousName is a qualified name, consisting of a name, a ".", and an Identifier, then the name to the
+    // left of the "." is first reclassified, for it is itself an AmbiguousName. There is then a choice:
+    //
+    // If the name to the left of the "." is reclassified as a PackageName, then:
+    //
+    // If the Identifier is a valid TypeIdentifier, and there is a package whose name is the name to the left of the
+    // ".", and that package contains a declaration of a type whose name is the same as the Identifier, then this
+    // AmbiguousName is reclassified as a TypeName.
+    //
+    // Otherwise, this AmbiguousName is reclassified as a PackageName. A later step determines whether or not a package
+    // of that name actually exists.
+
+    @Test
+    void ambiguousNameInQualifiedNameRequalifiedAsPackageNameLeadingToType() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        typeSolver.addDeclaration("a.b.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.b.C.d;" + "\n" +
+                        "} }", "a.b.C", NameCategory.AMBIGUOUS_NAME, NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    @Test
+    void ambiguousNameInQualifiedNameRequalifiedAsPackageNameNotLeadingToType() {
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.b.C.d;" + "\n" +
+                        "} }", "a.b.C", NameCategory.AMBIGUOUS_NAME, NameCategory.PACKAGE_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver()));
+    }
+
+    // If the AmbiguousName is a qualified name, consisting of a name, a ".", and an Identifier, then the name to the
+    // left of the "." is first reclassified, for it is itself an AmbiguousName. There is then a choice:
+    //
+    // If the name to the left of the "." is reclassified as a PackageName, then:
+    //
+    // If the Identifier is a valid TypeIdentifier, and there is a package whose name is the name to the left of the
+    // ".", and that package contains a declaration of a type whose name is the same as the Identifier, then this
+    // AmbiguousName is reclassified as a TypeName.
+    //
+    // Otherwise, this AmbiguousName is reclassified as a PackageName. A later step determines whether or not a package
+    // of that name actually exists.
+
+    @Test
+    void ambiguousNameInQualifiedNameRequalifiedAsTypeNameLeadingToField() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        ResolvedFieldDeclaration mockedFieldC = mock(ResolvedFieldDeclaration.class);
+        when(mockedC.asReferenceType()).thenReturn(mockedC);
+        when(mockedC.getAllMethods()).thenReturn(Collections.emptySet());
+        when(mockedFieldC.isStatic()).thenReturn(true);
+        when(mockedFieldC.getName()).thenReturn("d");
+        when(mockedC.getAllFields()).thenReturn(Arrays.asList(mockedFieldC));
+        typeSolver.addDeclaration("a.b.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.b.C.d.e;" + "\n" +
+                        "} }", "a.b.C.d", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    @Test
+    void ambiguousNameInQualifiedNameRequalifiedAsTypeNameLeadingToMethod() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        MethodUsage mockedMethodD = mock(MethodUsage.class);
+        when(mockedC.asReferenceType()).thenReturn(mockedC);
+        when(mockedMethodD.getName()).thenReturn("d");
+        when(mockedC.getAllFields()).thenReturn(Collections.emptyList());
+        when(mockedC.getAllMethods()).thenReturn(new HashSet<>(Arrays.asList(mockedMethodD)));
+        typeSolver.addDeclaration("a.b.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.b.C.d.e;" + "\n" +
+                        "} }", "a.b.C.d", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    @Test
+    void ambiguousNameInQualifiedNameRequalifiedAsTypeNameLeadingToInternalType() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+
+        ResolvedReferenceTypeDeclaration mockedD = mock(ResolvedReferenceTypeDeclaration.class);
+
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        when(mockedC.asReferenceType()).thenReturn(mockedC);
+        when(mockedC.getInternalType("d")).thenReturn(mockedD);
+        when(mockedC.hasInternalType("d")).thenReturn(true);
+        typeSolver.addDeclaration("a.b.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.b.C.d.e;" + "\n" +
+                        "} }", "a.b.C.d", NameCategory.AMBIGUOUS_NAME, NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    @Test
+    void ambiguousNameInQualifiedNameRequalifiedAsTypeNameLeadingToCompilationError() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        when(mockedC.asReferenceType()).thenReturn(mockedC);
+        when(mockedC.getAllFields()).thenReturn(Arrays.asList());
+        when(mockedC.getAllMethods()).thenReturn(Collections.emptySet());
+        typeSolver.addDeclaration("a.b.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.b.C.d.e;" + "\n" +
+                        "} }", "a.b.C.d", NameCategory.AMBIGUOUS_NAME, NameCategory.COMPILATION_ERROR, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    @Test
+    void ambiguousNameInQualifiedNameRequalifiedAsExpressionName() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedC = mock(ResolvedReferenceTypeDeclaration.class);
+        MethodUsage mockedMethodD = mock(MethodUsage.class);
+        when(mockedC.asReferenceType()).thenReturn(mockedC);
+        when(mockedMethodD.getName()).thenReturn("d");
+        when(mockedC.getAllFields()).thenReturn(Collections.emptyList());
+        when(mockedC.getAllMethods()).thenReturn(new HashSet<>(Arrays.asList(mockedMethodD)));
+        typeSolver.addDeclaration("a.b.C", mockedC);
+
+        assertNameInCodeIsDisambiguited("class B {  void foo() {\n" +
+                        "a.b.C.d.e.f;" + "\n" +
+                        "} }", "a.b.C.d.e", NameCategory.AMBIGUOUS_NAME, NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    // 6.5.4.1. Simple PackageOrTypeNames
+    //
+    // If the PackageOrTypeName, Q, is a valid TypeIdentifier and occurs in the scope of a type named Q, then the
+    // PackageOrTypeName is reclassified as a TypeName.
+
+    @Test
+    void packageOrTypeNameSimpleNameMatchingType() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedMyQualified = mock(ResolvedReferenceTypeDeclaration.class);
+        when(mockedMyQualified.asReferenceType()).thenReturn(mockedMyQualified);
+        typeSolver.addDeclaration("foo.myQualified", mockedMyQualified);
+
+        assertNameInCodeIsDisambiguited("package foo; class Bar {  Bar() { new myQualified.path.to.TypeName(); } }",
+                "myQualified", NameCategory.PACKAGE_OR_TYPE_NAME, NameCategory.TYPE_NAME,
+                ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    // Otherwise, the PackageOrTypeName is reclassified as a PackageName. The meaning of the PackageOrTypeName is
+    // the meaning of the reclassified name.
+
+    @Test
+    void packageOrTypeNameSimpleNameNotMatchingType() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+
+        assertNameInCodeIsDisambiguited("package foo; class Bar {  Bar() { new myQualified.path.to.TypeName(); } }",
+                "myQualified", NameCategory.PACKAGE_OR_TYPE_NAME, NameCategory.PACKAGE_NAME,
+                ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    // 6.5.4.2. Qualified PackageOrTypeNames
+    //
+    // Given a qualified PackageOrTypeName of the form Q.Id, if Id is a valid TypeIdentifier and the type or package
+    // denoted by Q has a member type named Id, then the qualified PackageOrTypeName name is reclassified as a
+    // TypeName.
+
+    @Test
+    void packageOrTypeNameQualifiedNameMatchingType() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+        ResolvedReferenceTypeDeclaration mockedMyQualified = mock(ResolvedReferenceTypeDeclaration.class);
+        when(mockedMyQualified.asReferenceType()).thenReturn(mockedMyQualified);
+        typeSolver.addDeclaration("myQualified.path", mockedMyQualified);
+
+        assertNameInCodeIsDisambiguited("package foo; class Bar {  Bar() { new myQualified.path.to.TypeName(); } }",
+                "myQualified.path", NameCategory.PACKAGE_OR_TYPE_NAME, NameCategory.TYPE_NAME,
+                ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+
+    // Otherwise, it is reclassified as a PackageName. The meaning of the qualified PackageOrTypeName is the meaning
+    // of the reclassified name.
+
+    @Test
+    void packageOrTypeNameQualifiedNameNotMatchingType() {
+        MemoryTypeSolver typeSolver = new MemoryTypeSolver();
+
+        assertNameInCodeIsDisambiguited("package foo; class Bar {  Bar() { new myQualified.path.to.TypeName(); } }",
+                "myQualified.path", NameCategory.PACKAGE_OR_TYPE_NAME, NameCategory.PACKAGE_NAME,
+                ParseStart.COMPILATION_UNIT,
+                new CombinedTypeSolver(new ReflectionTypeSolver(), typeSolver));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicTest.java
new file mode 100644
index 0000000..54491e6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicTest.java
@@ -0,0 +1,926 @@
+package com.github.javaparser.symbolsolver.resolution.naming;
+
+import com.github.javaparser.*;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.modules.ModuleDeclaration;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.symbolsolver.resolution.naming.NameRole.DECLARATION;
+import static com.github.javaparser.symbolsolver.resolution.naming.NameRole.REFERENCE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NameLogicTest extends AbstractNameLogicTest {
+
+
+    private void assertNameInCodeIsSyntactically(String code, String name, NameCategory nameCategory, ParseStart parseStart) {
+        Node nameNode = getNameInCode(code, name, parseStart);
+        assertEquals(nameCategory, NameLogic.syntacticClassificationAccordingToContext(nameNode));
+    }
+
+    @Test
+    void requiresModuleName() {
+        assertNameInCodeIsSyntactically("module com.mydeveloperplanet.jpmshello {\n" +
+                "    requires java.base;\n" +
+                "    requires java.xml;\n" +
+                "    requires com.mydeveloperplanet.jpmshi;\n" +
+                "}\n", "java.xml", NameCategory.MODULE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void exportsModuleName() {
+        assertNameInCodeIsSyntactically("module my.module{\n" +
+                "  exports my.packag to other.module, another.module;\n" +
+                "}", "other.module", NameCategory.MODULE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void opensModuleName() {
+        assertNameInCodeIsSyntactically("module client.modul{\n" +
+                "    opens some.client.packag to framework.modul;\n" +
+                "    requires framework.modul2;\n" +
+                "}", "framework.modul", NameCategory.MODULE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void exportsPackageName() {
+        assertNameInCodeIsSyntactically("module common.widget{\n" +
+                "  exports com.logicbig;\n" +
+                "}", "com.logicbig", NameCategory.PACKAGE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void opensPackageName() {
+        assertNameInCodeIsSyntactically("module foo {\n" +
+                "    opens com.example.bar;\n" +
+                "}", "com.example.bar", NameCategory.PACKAGE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void packageNameInPackageName() {
+        assertNameInCodeIsSyntactically("module foo {\n" +
+                "    opens com.example.bar;\n" +
+                "}", "com.example", NameCategory.PACKAGE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void usesTypeName() {
+        assertNameInCodeIsSyntactically("module modi.mod {\n" +
+                "    uses modi.api;\n" +
+                "}", "modi.api", NameCategory.TYPE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void providesTypeName() {
+        assertNameInCodeIsSyntactically("module foo {\n" +
+                "    provides com.modi.api.query.Query with ModuleQuery;\n" +
+                "}", "com.modi.api.query.Query", NameCategory.TYPE_NAME, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void singleTypeImportTypeName() {
+        assertNameInCodeIsSyntactically("import a.b.c;", "a.b.c",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void singleStaticTypeImportTypeName() {
+        assertNameInCodeIsSyntactically("import static a.B.c;", "a.B",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void singleStaticImportOnDemandTypeName() {
+        assertNameInCodeIsSyntactically("import static a.B.*;", "a.B",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void constructorDeclarationTypeName() {
+        assertNameInCodeIsSyntactically("A() { }", "A",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void annotationTypeName() {
+        assertNameInCodeIsSyntactically("@Anno class A {} ", "Anno",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classLiteralTypeName() {
+        assertNameInCodeIsSyntactically("Class<?> c = String.class;", "String",
+                NameCategory.TYPE_NAME, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void thisExprTypeName() {
+        assertNameInCodeIsSyntactically("Object o = String.this;", "String",
+                NameCategory.TYPE_NAME, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void qualifiedSuperFieldAccessTypeName() {
+        assertNameInCodeIsSyntactically("Object o = MyClass.super.myField;", "MyClass",
+                NameCategory.TYPE_NAME, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void qualifiedSuperCallTypeName() {
+        assertNameInCodeIsSyntactically("Object o = MyClass.super.myCall();", "MyClass",
+                NameCategory.TYPE_NAME, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void qualifiedSuperMethodReferenceTypeName() {
+        assertNameInCodeIsSyntactically("Object o = MyClass.super::myMethod;", "MyClass",
+                NameCategory.TYPE_NAME, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void extendsClauseTypeName() {
+        assertNameInCodeIsSyntactically("class Foo extends bar.MyClass { }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void implementsClauseTypeName() {
+        assertNameInCodeIsSyntactically("class Foo implements bar.MyClass { }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void returnTypeTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { bar.MyClass myMethod() {} }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void qualifiedAnnotationMemberTypeTypeName() {
+        assertNameInCodeIsSyntactically("@interface MyAnno { bar.MyClass myMember(); }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void unqualifiedAnnotationMemberTypeTypeName() {
+        assertNameInCodeIsSyntactically("@interface MyAnno { MyClass myMember(); }", "MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void throwClauseMethodTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { void myMethod() throws bar.MyClass {} }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void qualifiedThrowClauseConstructorTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { Foo() throws bar.MyClass {} }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void unualifiedThrowClauseConstructorTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { Foo() throws MyClass {} }", "MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void qualifiedFieldTypeTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { bar.MyClass myField; }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void fieldTypeTypeNameSecondAttempt() {
+        assertNameInCodeIsSyntactically("public class JavaParserInterfaceDeclaration extends AbstractTypeDeclaration implements InterfaceDeclaration {\n" +
+                        "private TypeSolver typeSolver; }", "TypeSolver",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void unqualifiedFieldTypeTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { MyClass myField; }", "MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void qualifiedFormalParameterOfMethodTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { void myMethod(bar.MyClass param) {} }", "bar.MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void unqualifiedFormalParameterOfMethodTypeName() {
+        assertNameInCodeIsSyntactically("class Foo { void myMethod(MyClass param) {} }", "MyClass",
+                NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void receiverParameterOfMethodTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod(Foo this) {}", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void variableDeclarationTypeTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { Foo myVar; }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void exceptionParameterTypeTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { try { } catch(Foo e) { } }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void explicitParameterTypeInConstructorCallTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { new Call<Foo>(); }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void explicitParameterTypeInMethodCallTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { new Call().<Foo>myMethod(); }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void instantiationCallTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { new Foo(); }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void instantiationCallOfAnonymousTypeTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { new Foo() { void method() { } } ; }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void arrayCreationExpressionTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { new Foo[0]; }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void castTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { Object o = (Foo)someField; }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void instanceOfTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { if (myValue instanceof Foo) { }; }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void methodReferenceTypeName() {
+        assertNameInCodeIsSyntactically("void myMethod() { Object o = Foo::myMethod; }", "Foo",
+                NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void qualifiedConstructorSuperClassInvocationExpressionName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { anExpression.super(); } } ", "anExpression",
+                NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void qualifiedClassInstanceCreationExpressionName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { anExpression.new MyClass(); } } ", "anExpression",
+                NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void arrayReferenceExpressionName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { anExpression[0]; } } ", "anExpression",
+                NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void postfixExpressionName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { anExpression++; } } ", "anExpression",
+                NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void leftHandAssignmentExpressionName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { anExpression = 2; } } ", "anExpression",
+                NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void variableAccessInTryWithResourceExpressionName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { try (anExpression) { }; } } ", "anExpression",
+                NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void variableAccessInTryWithResourceWothTypeExpressionName() {
+        assertNameInCodeIsSyntactically("class Bar {  Bar() { try (Object o = anExpression) { }; } } ", "anExpression",
+                NameCategory.EXPRESSION_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void methodInvocationMethodName() {
+        assertNameInCodeIsSyntactically("class Bar {  Bar() { myMethod(); } } ", "myMethod",
+                NameCategory.METHOD_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void leftOfQualifiedTypeNamePackageOrTypeName() {
+        assertNameInCodeIsSyntactically("class Bar {  Bar() { new myQualified.path.to.TypeName(); } } ", "myQualified.path.to",
+                NameCategory.PACKAGE_OR_TYPE_NAME, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeIsSyntactically("class Bar {  Bar() { new myQualified.path.to.TypeName(); } } ", "myQualified.path",
+                NameCategory.PACKAGE_OR_TYPE_NAME, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeIsSyntactically("class Bar {  Bar() { new myQualified.path.to.TypeName(); } } ", "myQualified",
+                NameCategory.PACKAGE_OR_TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void typeImportOnDemandPackageOrTypeName() {
+        assertNameInCodeIsSyntactically("import a.B.*;", "a.B",
+                NameCategory.PACKAGE_OR_TYPE_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void leftOfExpressionNameAmbiguousName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a.b.c",
+                NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a.b",
+                NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a",
+                NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void leftOfMethodCallAmbiguousName() {
+        assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.aMethod(); } } ", "a.b.c",
+                NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
+    }
+
+
+
+    private void assertNameInCodeHasRole(String code, String name, NameRole nameRole, ParseStart parseStart) {
+        Node nameNode = getNameInCode(code, name, parseStart);
+        assertEquals(nameRole, NameLogic.classifyRole(nameNode));
+    }
+
+    private void assertIsSimpleName(String code, String name, ParseStart parseStart) {
+        Node nameNode = getNameInCode(code, name, parseStart);
+        assertTrue(NameLogic.isSimpleName(nameNode));
+    }
+
+    private void assertIsQualifiedName(String code, String name, ParseStart parseStart) {
+        Node nameNode = getNameInCode(code, name, parseStart);
+        assertTrue(NameLogic.isQualifiedName(nameNode));
+    }
+
+    @Test
+    void identifyNamesInSimpleExamples() {
+        String code = "package a.b.c; class A { void foo(int param) { return a.b.c.D.e; } }";
+        CompilationUnit cu = StaticJavaParser.parse(code);
+
+        assertEquals(false, NameLogic.isAName(cu));
+        assertEquals(false, NameLogic.isAName(cu.getPackageDeclaration().get()));
+
+        Name packageName = cu.getPackageDeclaration().get().getName();
+        assertEquals(true, NameLogic.isAName(packageName));
+        assertEquals(true, NameLogic.isAName(packageName.getQualifier().get()));
+        assertEquals(true, NameLogic.isAName(packageName.getQualifier().get().getQualifier().get()));
+
+        ClassOrInterfaceDeclaration classA = cu.getType(0).asClassOrInterfaceDeclaration();
+        assertEquals(false, NameLogic.isAName(classA));
+        assertEquals(true, NameLogic.isAName(classA.getName()));
+
+        MethodDeclaration methodFoo = classA.getMethods().get(0);
+        assertEquals(false, NameLogic.isAName(methodFoo));
+        assertEquals(true, NameLogic.isAName(methodFoo.getName()));
+        assertEquals(false, NameLogic.isAName(methodFoo.getParameter(0)));
+        assertEquals(true, NameLogic.isAName(methodFoo.getParameter(0).getName()));
+        assertEquals(false, NameLogic.isAName(methodFoo.getParameter(0).getType()));
+        assertEquals(false, NameLogic.isAName(methodFoo.getType()));
+
+        ReturnStmt returnStmt = methodFoo.getBody().get().getStatements().get(0).asReturnStmt();
+        assertEquals(false, NameLogic.isAName(returnStmt));
+        assertEquals(true, NameLogic.isAName(returnStmt.getExpression().get()));
+        FieldAccessExpr fieldAccessExpr = returnStmt.getExpression().get().asFieldAccessExpr();
+        assertEquals(true, NameLogic.isAName(fieldAccessExpr
+                .getScope())); // a.b.c.D
+        assertEquals(true, NameLogic.isAName(fieldAccessExpr
+                .getScope().asFieldAccessExpr()
+                .getScope())); // a.b.c
+        assertEquals(true, NameLogic.isAName(fieldAccessExpr
+                .getScope().asFieldAccessExpr()
+                .getScope().asFieldAccessExpr()
+                .getScope())); // a.b
+        assertEquals(true, NameLogic.isAName(fieldAccessExpr
+                .getScope().asFieldAccessExpr()
+                .getScope().asFieldAccessExpr()
+                .getScope().asFieldAccessExpr()
+                .getScope())); // a
+    }
+
+    @Test
+    void identifyNameRolesInSimpleExamples() {
+        String code = "package a.b.c; class A { void foo(int param) { return a.b.c.D.e; } }";
+        CompilationUnit cu = StaticJavaParser.parse(code);
+
+        Name packageName = cu.getPackageDeclaration().get().getName();
+        assertEquals(DECLARATION, NameLogic.classifyRole(packageName));
+        assertEquals(DECLARATION, NameLogic.classifyRole(packageName.getQualifier().get()));
+        assertEquals(DECLARATION, NameLogic.classifyRole(packageName.getQualifier().get().getQualifier().get()));
+
+        ClassOrInterfaceDeclaration classA = cu.getType(0).asClassOrInterfaceDeclaration();
+        assertEquals(DECLARATION, NameLogic.classifyRole(classA.getName()));
+
+        MethodDeclaration methodFoo = classA.getMethods().get(0);
+        assertEquals(DECLARATION, NameLogic.classifyRole(methodFoo.getName()));
+        assertEquals(DECLARATION, NameLogic.classifyRole(methodFoo.getParameter(0).getName()));
+
+        ReturnStmt returnStmt = methodFoo.getBody().get().getStatements().get(0).asReturnStmt();
+        assertEquals(REFERENCE, NameLogic.classifyRole(returnStmt.getExpression().get())); // a.b.c.D.e
+        FieldAccessExpr fieldAccessExpr = returnStmt.getExpression().get().asFieldAccessExpr();
+        assertEquals(REFERENCE, NameLogic.classifyRole(fieldAccessExpr
+                .getScope())); // a.b.c.D
+        assertEquals(REFERENCE, NameLogic.classifyRole(fieldAccessExpr
+                .getScope().asFieldAccessExpr()
+                .getScope())); // a.b.c
+        assertEquals(REFERENCE, NameLogic.classifyRole(fieldAccessExpr
+                .getScope().asFieldAccessExpr()
+                .getScope().asFieldAccessExpr()
+                .getScope())); // a.b
+        assertEquals(REFERENCE, NameLogic.classifyRole(fieldAccessExpr
+                .getScope().asFieldAccessExpr()
+                .getScope().asFieldAccessExpr()
+                .getScope().asFieldAccessExpr()
+                .getScope())); // a
+    }
+
+    @Test
+    void nameAsStringModuleName() {
+        ModuleDeclaration md = parse("module com.mydeveloperplanet.jpmshello {\n" +
+                "    requires java.base;\n" +
+                "    requires java.xml;\n" +
+                "    requires com.mydeveloperplanet.jpmshi;\n" +
+                "}\n", ParseStart.MODULE_DECLARATION);
+        assertEquals("com.mydeveloperplanet.jpmshello", NameLogic.nameAsString(md.getName()));
+    }
+
+    @Test
+    void nameAsStringClassName() {
+        CompilationUnit cu = parse("class Foo extends bar.MyClass { }", ParseStart.COMPILATION_UNIT);
+        assertEquals("Foo", NameLogic.nameAsString(cu.getType(0).getName()));
+    }
+
+    @Test
+    void qualifiedModuleName() {
+        assertIsQualifiedName("module com.mydeveloperplanet.jpmshello {\n" +
+                "    requires java.base;\n" +
+                "    requires java.xml;\n" +
+                "    requires com.mydeveloperplanet.jpmshi;\n" +
+                "}\n", "com.mydeveloperplanet.jpmshello", ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void simpleNameUnqualifiedAnnotationMemberTypeTypeName() {
+        assertIsSimpleName("@interface MyAnno { MyClass myMember(); }", "MyClass",
+                ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleModuleName() {
+        assertNameInCodeHasRole("module com.mydeveloperplanet.jpmshello {\n" +
+                "    requires java.base;\n" +
+                "    requires java.xml;\n" +
+                "    requires com.mydeveloperplanet.jpmshi;\n" +
+                "}\n", "com.mydeveloperplanet.jpmshello", DECLARATION, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleRequiresModuleName() {
+        assertNameInCodeHasRole("module com.mydeveloperplanet.jpmshello {\n" +
+                "    requires java.base;\n" +
+                "    requires java.xml;\n" +
+                "    requires com.mydeveloperplanet.jpmshi;\n" +
+                "}\n", "java.xml", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleExportsModuleName() {
+        assertNameInCodeHasRole("module my.module{\n" +
+                "  exports my.packag to other.module, another.module;\n" +
+                "}", "other.module", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleOpensModuleName() {
+        assertNameInCodeHasRole("module client.modul{\n" +
+                "    opens some.client.packag to framework.modul;\n" +
+                "    requires framework.modul2;\n" +
+                "}", "framework.modul", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleExportsPackageName() {
+        assertNameInCodeHasRole("module common.widget{\n" +
+                "  exports com.logicbig;\n" +
+                "}", "com.logicbig", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleOpensPackageName() {
+        assertNameInCodeHasRole("module foo {\n" +
+                "    opens com.example.bar;\n" +
+                "}", "com.example.bar", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRolePackageNameInPackageName() {
+        assertNameInCodeHasRole("module foo {\n" +
+                "    opens com.example.bar;\n" +
+                "}", "com.example", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleUsesTypeName() {
+        assertNameInCodeHasRole("module modi.mod {\n" +
+                "    uses modi.api;\n" +
+                "}", "modi.api", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleProvidesTypeName() {
+        assertNameInCodeHasRole("module foo {\n" +
+                "    provides com.modi.api.query.Query with ModuleQuery;\n" +
+                "}", "com.modi.api.query.Query", REFERENCE, ParseStart.MODULE_DECLARATION);
+    }
+
+    @Test
+    void classifyRoleSingleTypeImportTypeName() {
+        assertNameInCodeHasRole("import a.b.c;", "a.b.c",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleSingleStaticTypeImportTypeName() {
+        assertNameInCodeHasRole("import static a.B.c;", "a.B",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleSingleStaticImportOnDemandTypeName() {
+        assertNameInCodeHasRole("import static a.B.*;", "a.B",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleConstructorDeclarationTypeName() {
+        assertNameInCodeHasRole("A() { }", "A",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleAnnotationTypeName() {
+        assertNameInCodeHasRole("@Anno class A {} ", "Anno",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleClassName() {
+        assertNameInCodeHasRole("@Anno class A {} ", "A",
+                DECLARATION, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleClassLiteralTypeName() {
+        assertNameInCodeHasRole("Class<?> c = String.class;", "String",
+                REFERENCE, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void classifyRoleThisExprTypeName() {
+        assertNameInCodeHasRole("Object o = String.this;", "String",
+                REFERENCE, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void classifyRoleQualifiedSuperFieldAccessTypeName() {
+        assertNameInCodeHasRole("Object o = MyClass.super.myField;", "MyClass",
+                REFERENCE, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void classifyRoleQualifiedSuperCallTypeName() {
+        assertNameInCodeHasRole("Object o = MyClass.super.myCall();", "MyClass",
+                REFERENCE, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void classifyRoleQualifiedSuperMethodReferenceTypeName() {
+        assertNameInCodeHasRole("Object o = MyClass.super::myMethod;", "MyClass",
+                REFERENCE, ParseStart.STATEMENT);
+    }
+
+    @Test
+    void classifyRoleExtendsClauseTypeName() {
+        assertNameInCodeHasRole("class Foo extends bar.MyClass { }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleImplementsClauseTypeName() {
+        assertNameInCodeHasRole("class Foo implements bar.MyClass { }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleReturnTypeTypeName() {
+        assertNameInCodeHasRole("class Foo { bar.MyClass myMethod() {} }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleQualifiedAnnotationMemberTypeTypeName() {
+        assertNameInCodeHasRole("@interface MyAnno { bar.MyClass myMember(); }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleAnnotationName() {
+        assertNameInCodeHasRole("@interface MyAnno { bar.MyClass myMember(); }", "MyAnno",
+                DECLARATION, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleUnqualifiedAnnotationMemberTypeTypeName() {
+        assertNameInCodeHasRole("@interface MyAnno { MyClass myMember(); }", "MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleThrowClauseMethodTypeName() {
+        assertNameInCodeHasRole("class Foo { void myMethod() throws bar.MyClass {} }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleQualifiedThrowClauseConstructorTypeName() {
+        assertNameInCodeHasRole("class Foo { Foo() throws bar.MyClass {} }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleUnualifiedThrowClauseConstructorTypeName() {
+        assertNameInCodeHasRole("class Foo { Foo() throws MyClass {} }", "MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleQualifiedFieldTypeTypeName() {
+        assertNameInCodeHasRole("class Foo { bar.MyClass myField; }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleFieldTypeTypeNameSecondAttempt() {
+        assertNameInCodeHasRole("public class JavaParserInterfaceDeclaration extends AbstractTypeDeclaration implements InterfaceDeclaration {\n" +
+                        "private TypeSolver typeSolver; }", "TypeSolver",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleUnqualifiedFieldTypeTypeName() {
+        assertNameInCodeHasRole("class Foo { MyClass myField; }", "MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleFieldName() {
+        assertNameInCodeHasRole("class Foo { MyClass myField; }", "myField",
+                DECLARATION, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleQualifiedFormalParameterOfMethodTypeName() {
+        assertNameInCodeHasRole("class Foo { void myMethod(bar.MyClass param) {} }", "bar.MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleUnqualifiedFormalParameterOfMethodTypeName() {
+        assertNameInCodeHasRole("class Foo { void myMethod(MyClass param) {} }", "MyClass",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleMethodName() {
+        assertNameInCodeHasRole("class Foo { void myMethod(MyClass param) {} }", "myMethod",
+                DECLARATION, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleReceiverParameterOfMethodTypeName() {
+        assertNameInCodeHasRole("void myMethod(Foo this) {}", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleVariableDeclarationTypeTypeName() {
+        assertNameInCodeHasRole("void myMethod() { Foo myVar; }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleExceptionParameterTypeTypeName() {
+        assertNameInCodeHasRole("void myMethod() { try { } catch(Foo e) { } }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleExceptionParameterName() {
+        assertNameInCodeHasRole("void myMethod() { try { } catch(Foo e) { } }", "e",
+                DECLARATION, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleExplicitParameterTypeInConstructorCallTypeName() {
+        assertNameInCodeHasRole("void myMethod() { new Call<Foo>(); }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleExplicitParameterTypeInMethodCallTypeName() {
+        assertNameInCodeHasRole("void myMethod() { new Call().<Foo>myMethod(); }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleInstantiationCallTypeName() {
+        assertNameInCodeHasRole("void myMethod() { new Foo(); }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleInstantiationCallOfAnonymousTypeTypeName() {
+        assertNameInCodeHasRole("void myMethod() { new Foo() { void method() { } } ; }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleArrayCreationExpressionTypeName() {
+        assertNameInCodeHasRole("void myMethod() { new Foo[0]; }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleCastTypeName() {
+        assertNameInCodeHasRole("void myMethod() { Object o = (Foo)someField; }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleInstanceOfTypeName() {
+        assertNameInCodeHasRole("void myMethod() { if (myValue instanceof Foo) { }; }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleMethodReferenceTypeName() {
+        assertNameInCodeHasRole("void myMethod() { Object o = Foo::myMethod; }", "Foo",
+                REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleQualifiedConstructorSuperClassInvocationExpressionName() {
+        assertNameInCodeHasRole("class Bar { Bar() { anExpression.super(); } } ", "anExpression",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleQualifiedClassInstanceCreationExpressionName() {
+        assertNameInCodeHasRole("class Bar { Bar() { anExpression.new MyClass(); } } ", "anExpression",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleArrayReferenceExpressionName() {
+        assertNameInCodeHasRole("class Bar { Bar() { anExpression[0]; } } ", "anExpression",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRolePostfixExpressionName() {
+        assertNameInCodeHasRole("class Bar { Bar() { anExpression++; } } ", "anExpression",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleLeftHandAssignmentExpressionName() {
+        assertNameInCodeHasRole("class Bar { Bar() { anExpression = 2; } } ", "anExpression",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleVariableAccessInTryWithResourceExpressionName() {
+        assertNameInCodeHasRole("class Bar { Bar() { try (anExpression) { }; } } ", "anExpression",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleVariableAccessInTryWithResourceWithTypeExpressionName() {
+        assertNameInCodeHasRole("class Bar {  Bar() { try (Object o = anExpression) { }; } } ", "anExpression",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyTryWithResourceName() {
+        assertNameInCodeHasRole("class Bar {  Bar() { try (Object o = anExpression) { }; } } ", "o",
+                DECLARATION, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleMethodInvocationMethodName() {
+        assertNameInCodeHasRole("class Bar {  Bar() { myMethod(); } } ", "myMethod",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleLeftOfQualifiedTypeNamePackageOrTypeName() {
+        assertNameInCodeHasRole("class Bar {  Bar() { new myQualified.path.to.TypeName(); } } ", "myQualified.path.to",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeHasRole("class Bar {  Bar() { new myQualified.path.to.TypeName(); } } ", "myQualified.path",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeHasRole("class Bar {  Bar() { new myQualified.path.to.TypeName(); } } ", "myQualified",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleTypeImportOnDemandPackageOrTypeName() {
+        assertNameInCodeHasRole("import a.B.*;", "a.B",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleLeftOfExpressionNameAmbiguousName() {
+        assertNameInCodeHasRole("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a.b.c",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeHasRole("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a.b",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+        assertNameInCodeHasRole("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void classifyRoleLeftOfMethodCallAmbiguousName() {
+        assertNameInCodeHasRole("class Bar { Bar() { a.b.c.aMethod(); } } ", "a.b.c",
+                REFERENCE, ParseStart.COMPILATION_UNIT);
+    }
+
+    @Test
+    void defaultValueTypeName() {
+        assertNameInCodeIsSyntactically("@RequestForEnhancement(\n" +
+                        "    id       = 2868724,\n" +
+                        "    synopsis = \"Provide time-travel functionality\",\n" +
+                        "    engineer = \"Mr. Peabody\",\n" +
+                        "    date     = anExpression" +
+                        ")\n" +
+                        "public static void travelThroughTime(Date destination) {  }",
+                "anExpression", NameCategory.AMBIGUOUS_NAME, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleDefaultValueTypeName() {
+        assertNameInCodeHasRole("@RequestForEnhancement(\n" +
+                        "    id       = 2868724,\n" +
+                        "    synopsis = \"Provide time-travel functionality\",\n" +
+                        "    engineer = \"Mr. Peabody\",\n" +
+                        "    date     = anExpression" +
+                        ")\n" +
+                        "public static void travelThroughTime(Date destination) {  }",
+                "anExpression", REFERENCE, ParseStart.CLASS_BODY);
+    }
+
+    @Test
+    void classifyRoleDefaultValueDeclaration() {
+        assertNameInCodeHasRole("@RequestForEnhancement(\n" +
+                        "    id       = 2868724,\n" +
+                        "    synopsis = \"Provide time-travel functionality\",\n" +
+                        "    engineer = \"Mr. Peabody\",\n" +
+                        "    date     = anExpression" +
+                        ")\n" +
+                        "public static void travelThroughTime(Date destination) {  }",
+                "date", DECLARATION, ParseStart.CLASS_BODY);
+    }
+    
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicTestingJss060Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicTestingJss060Test.java
new file mode 100644
index 0000000..deaf97b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/naming/NameLogicTestingJss060Test.java
@@ -0,0 +1,499 @@
+package com.github.javaparser.symbolsolver.resolution.naming;
+
+import com.github.javaparser.SlowTest;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.github.javaparser.StaticJavaParser.parse;
+
+@SlowTest
+class NameLogicTestingJss060Test extends AbstractResolutionTest {
+
+    private static final Path root = adaptPath("src/test/test_sourcecode/javasymbolsolver_0_6_0");
+    private static final Path src = root.resolve("src");
+
+    private void classifyRoles(String projectName, String className) throws IOException {
+        Path sourceFile = src.resolve(projectName + "/" + className + ".java");
+        CompilationUnit cu = parse(sourceFile);
+
+        List<Node> names = new LinkedList<>();
+        names.addAll(cu.findAll(Name.class).stream().filter(Name::isTopLevel).collect(Collectors.toList()));
+        names.addAll(cu.findAll(SimpleName.class));
+        names.forEach(n -> {
+            NameRole role = NameLogic.classifyRole(n);
+        });
+    }
+
+    private void classifyReferences(String projectName, String className) throws IOException {
+        Path sourceFile = src.resolve(projectName + "/" + className + ".java");
+        CompilationUnit cu = parse(sourceFile);
+
+        List<Node> names = new LinkedList<>();
+        names.addAll(cu.findAll(Name.class).stream().filter(Name::isTopLevel).collect(Collectors.toList()));
+        names.addAll(cu.findAll(SimpleName.class));
+        names.forEach(n -> {
+            if (NameLogic.classifyRole(n) == NameRole.REFERENCE) {
+                NameCategory nameCategory = NameLogic.syntacticClassificationAccordingToContext(n);
+            }
+        });
+    }
+
+    @Test
+    void classifyRoleToFileToCoreSourceFileInfoExtractor() throws IOException {
+        classifyRoles("java-symbol-solver-core",
+                "com/github/javaparser/symbolsolver/SourceFileInfoExtractor");
+    }
+
+    @Test
+    void classifyRolesCoreCoreResolution() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/core/resolution/Context");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/core/resolution/ContextHelper");
+    }
+
+    @Test
+    void classifyRolesCoreDeclarationsCommon() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic");
+    }
+
+    @Test
+    void classifyRolesCoreJavaparserNavigator() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparser/Navigator");
+    }
+
+    @Test
+    void classifyRolesCoreJavaparsermodel() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException");
+    }
+
+    @Test
+    void classifyRolesCoreJavaparsermodelContexts() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext");
+    }
+
+    @Test
+    void classifyRolesCoreJavaparsermodelJavaParserAnonymousClassDeclaration() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration");
+    }
+
+    @Test
+    void classifyRolesCoreJavaparsermodelJavaParserInterfaceDeclaration() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration");
+    }
+
+    @Test
+    void classifyRolesCoreJavaparsermodelDeclarations() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration");
+    }
+
+    @Test
+    void classifyRolesCoreJavaparsermodelDeclarators() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator");
+    }
+
+    @Test
+    void classifyRolesCoreJavassistmodel() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils");
+    }
+
+    @Test
+    void classifyRolesCoreModelTypesystem() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/model/typesystem/LazyType");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl");
+    }
+
+    @Test
+    void classifyRolesCoreReflectionmodel() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/MyObjectProvider");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFieldDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter");
+    }
+
+    @Test
+    void classifyRolesCoreReflectionmodelComparators() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/ClassComparator");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/MethodComparator");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/ParameterComparator");
+    }
+
+    @Test
+    void classifyRolesCoreResolution() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/ConstructorResolutionLogic");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/SymbolDeclarator");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/SymbolSolver");
+    }
+
+    @Test
+    void classifyRolesCoreResolutionTypesolvers() throws IOException {
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver");
+        classifyRoles("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver");
+    }
+
+    @Test
+    void classifyRolesLogic() throws IOException {
+        classifyRoles("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration");
+        classifyRoles("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration");
+        classifyRoles("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ConfilictingGenericTypesException");
+        classifyRoles("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic");
+        classifyRoles("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceContext");
+        classifyRoles("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceVariableType");
+        classifyRoles("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ObjectProvider");
+    }
+
+    @Test
+    void classifyRolesModelDeclarations() throws IOException {
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/AccessLevel");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/AnnotationDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ClassDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ConstructorDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/Declaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/EnumDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/FieldDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/HasAccessLevel");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/InterfaceDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/MethodAmbiguityException");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/MethodDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/MethodLikeDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ParameterDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ReferenceTypeDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/TypeDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/TypeParameterDeclaration");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/TypeParametrizable");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ValueDeclaration");
+    }
+
+    @Test
+    void classifyRolesModelMethodsMethodUsage() throws IOException {
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/methods/MethodUsage");
+    }
+
+    @Test
+    void classifyRolesModelResolution() throws IOException {
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/SymbolReference");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/TypeSolver");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/UnsolvedSymbolException");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/Value");
+    }
+
+    @Test
+    void classifyRolesModelTypesystemReferenceType() throws IOException {
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/ReferenceType");
+    }
+
+    @Test
+    void classifyRolesModelTypesystem() throws IOException {
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/ArrayType");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/LambdaConstraintType");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/NullType");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/PrimitiveType");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/Type");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/TypeTransformer");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/TypeVariable");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/VoidType");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/Wildcard");
+    }
+
+    @Test
+    void classifyRolesModelTypesystemParametrization() throws IOException {
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametersMap");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParameterValueProvider");
+        classifyRoles("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametrized");
+    }
+
+    @Test
+    void classifyReferencesToFileToCoreSourceFileInfoExtractor() throws IOException {
+        classifyReferences("java-symbol-solver-core",
+                "com/github/javaparser/symbolsolver/SourceFileInfoExtractor");
+    }
+
+    @Test
+    void classifyReferencesCoreCoreResolution() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/core/resolution/Context");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/core/resolution/ContextHelper");
+    }
+
+    @Test
+    void classifyReferencesCoreDeclarationsCommon() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic");
+    }
+
+    @Test
+    void classifyReferencesCoreJavaparserNavigator() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparser/Navigator");
+    }
+
+    @Test
+    void classifyReferencesCoreJavaparsermodel() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException");
+    }
+
+    @Test
+    void classifyReferencesCoreJavaparsermodelContexts() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext");
+    }
+
+    @Test
+    void classifyReferencesCoreJavaparsermodelJavaParserAnonymousClassDeclaration() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration");
+    }
+
+    @Test
+    void classifyReferencesCoreJavaparsermodelJavaParserInterfaceDeclaration() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration");
+    }
+
+    @Test
+    void classifyReferencesCoreJavaparsermodelDeclarations() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration");
+    }
+
+    @Test
+    void classifyReferencesCoreJavaparsermodelDeclarators() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator");
+    }
+
+    @Test
+    void classifyReferencesCoreJavassistmodel() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils");
+    }
+
+    @Test
+    void classifyReferencesCoreModelTypesystem() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/model/typesystem/LazyType");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl");
+    }
+
+    @Test
+    void classifyReferencesCoreReflectionmodel() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/MyObjectProvider");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFieldDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter");
+    }
+
+    @Test
+    void classifyReferencesCoreReflectionmodelComparators() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/ClassComparator");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/MethodComparator");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/reflectionmodel/comparators/ParameterComparator");
+    }
+
+    @Test
+    void classifyReferencesCoreResolution() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/ConstructorResolutionLogic");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/SymbolDeclarator");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/SymbolSolver");
+    }
+
+    @Test
+    void classifyReferencesCoreResolutionTypesolvers() throws IOException {
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver");
+        classifyReferences("java-symbol-solver-core", "com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver");
+    }
+
+    @Test
+    void classifyReferencesLogic() throws IOException {
+        classifyReferences("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration");
+        classifyReferences("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration");
+        classifyReferences("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ConfilictingGenericTypesException");
+        classifyReferences("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic");
+        classifyReferences("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceContext");
+        classifyReferences("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/InferenceVariableType");
+        classifyReferences("java-symbol-solver-logic", "com/github/javaparser/symbolsolver/logic/ObjectProvider");
+    }
+
+    @Test
+    void classifyReferencesModelDeclarations() throws IOException {
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/AccessLevel");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/AnnotationDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ClassDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ConstructorDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/Declaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/EnumDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/FieldDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/HasAccessLevel");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/InterfaceDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/MethodAmbiguityException");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/MethodDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/MethodLikeDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ParameterDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ReferenceTypeDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/TypeDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/TypeParameterDeclaration");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/TypeParametrizable");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/declarations/ValueDeclaration");
+    }
+
+    @Test
+    void classifyReferencesModelMethodsMethodUsage() throws IOException {
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/methods/MethodUsage");
+    }
+
+    @Test
+    void classifyReferencesModelResolution() throws IOException {
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/SymbolReference");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/TypeSolver");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/UnsolvedSymbolException");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/resolution/Value");
+    }
+
+    @Test
+    void classifyReferencesModelTypesystemReferenceType() throws IOException {
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/ReferenceType");
+    }
+
+    @Test
+    void classifyReferencesModelTypesystem() throws IOException {
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/ArrayType");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/LambdaConstraintType");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/NullType");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/PrimitiveType");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/Type");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/TypeTransformer");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/TypeVariable");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/VoidType");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/Wildcard");
+    }
+
+    @Test
+    void classifyReferencesModelTypesystemParametrization() throws IOException {
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametersMap");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParameterValueProvider");
+        classifyReferences("java-symbol-solver-model", "com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametrized");
+    }
+    
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/reflectionmodel/SymbolResolutionResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/reflectionmodel/SymbolResolutionResolutionTest.java
index 8e0989f..e3eecbc 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/reflectionmodel/SymbolResolutionResolutionTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/reflectionmodel/SymbolResolutionResolutionTest.java
@@ -16,7 +16,6 @@
 
 package com.github.javaparser.symbolsolver.resolution.reflectionmodel;
 
-import com.github.javaparser.ParseException;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
@@ -30,14 +29,14 @@
 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
 import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class SymbolResolutionResolutionTest extends AbstractResolutionTest {
+class SymbolResolutionResolutionTest extends AbstractResolutionTest {
 
     @Test
-    public void getTypeOfField() {
+    void getTypeOfField() {
         CompilationUnit cu = parseSample("ReflectionFieldOfItself");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MyClass");
         VariableDeclarator field = Navigator.demandField(clazz, "PUBLIC");
@@ -48,7 +47,7 @@
     }
 
     @Test
-    public void getTypeOfFieldAccess() {
+    void getTypeOfFieldAccess() {
         CompilationUnit cu = parseSample("ReflectionFieldOfItself");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MyClass");
         VariableDeclarator field = Navigator.demandField(clazz, "PUBLIC");
@@ -59,7 +58,7 @@
     }
 
     @Test
-    public void conditionalExpressionExample() {
+    void conditionalExpressionExample() {
         CompilationUnit cu = parseSample("JreConditionalExpression");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MyClass");
         MethodDeclaration method = Navigator.demandMethod(clazz, "foo1");
@@ -72,7 +71,7 @@
     }
 
     @Test
-    public void conditionalExpressionExampleFollowUp1() {
+    void conditionalExpressionExampleFollowUp1() {
         CompilationUnit cu = parseSample("JreConditionalExpression");
         ClassOrInterfaceDeclaration clazz = Navigator.demandClass(cu, "MyClass");
         MethodDeclaration method = Navigator.demandMethod(clazz, "foo1");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SameAsBoundTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SameAsBoundTest.java
index ba58dc7..f42a27a 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SameAsBoundTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SameAsBoundTest.java
@@ -7,19 +7,19 @@
 import com.github.javaparser.symbolsolver.resolution.typeinference.InferenceVariable;
 import com.github.javaparser.symbolsolver.resolution.typeinference.Instantiation;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.Optional;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class SameAsBoundTest {
+class SameAsBoundTest {
 
     private TypeSolver typeSolver = new ReflectionTypeSolver();
     private ResolvedType stringType = new ReferenceTypeImpl(new ReflectionTypeSolver().solveType(String.class.getCanonicalName()), typeSolver);
 
     @Test
-    public void recognizeInstantiation() {
+    void recognizeInstantiation() {
         // { α = String } contains a single bound, instantiating α as String.
         InferenceVariable inferenceVariable = new InferenceVariable("α", null);
         Bound bound1 = new SameAsBound(inferenceVariable, stringType);
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBoundTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBoundTest.java
index ecda077..2ba3619 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBoundTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/bounds/SubtypeOfBoundTest.java
@@ -8,17 +8,17 @@
 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
 import com.github.javaparser.symbolsolver.resolution.typeinference.*;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 
 import static com.github.javaparser.symbolsolver.resolution.typeinference.TypeHelper.isProperType;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.mock;
 
-public class SubtypeOfBoundTest {
+class SubtypeOfBoundTest {
 
     private TypeSolver typeSolver = new ReflectionTypeSolver();
     private ResolvedReferenceType iterableType = new ReferenceTypeImpl(new ReflectionTypeSolver().solveType(Iterable.class.getCanonicalName()), typeSolver);
@@ -28,7 +28,7 @@
     private ResolvedType objectType = new ReferenceTypeImpl(new ReflectionTypeSolver().solveType(Object.class.getCanonicalName()), typeSolver);
 
     @Test
-    public void recognizeProperLowerBound1() {
+    void recognizeProperLowerBound1() {
         ResolvedTypeParameterDeclaration typeParameterDeclaration = mock(ResolvedTypeParameterDeclaration.class);
 
         // { Integer <: α, Double <: α, α <: Object } describes two proper lower bounds and one proper upper bound for α.
@@ -40,7 +40,7 @@
     }
 
     @Test
-    public void recognizeProperLowerBound2() {
+    void recognizeProperLowerBound2() {
         ResolvedTypeParameterDeclaration typeParameterDeclaration = mock(ResolvedTypeParameterDeclaration.class);
 
         // { Integer <: α, Double <: α, α <: Object } describes two proper lower bounds and one proper upper bound for α.
@@ -52,7 +52,7 @@
     }
 
     @Test
-    public void recognizeProperUpperBound1() {
+    void recognizeProperUpperBound1() {
         ResolvedTypeParameterDeclaration typeParameterDeclaration = mock(ResolvedTypeParameterDeclaration.class);
 
         // { Integer <: α, Double <: α, α <: Object } describes two proper lower bounds and one proper upper bound for α.
@@ -64,7 +64,7 @@
     }
 
     @Test
-    public void recognizeProperUpperBound2() {
+    void recognizeProperUpperBound2() {
         ResolvedTypeParameterDeclaration typeParameterDeclaration1 = mock(ResolvedTypeParameterDeclaration.class);
         ResolvedTypeParameterDeclaration typeParameterDeclaration2 = mock(ResolvedTypeParameterDeclaration.class);
         // { α <: Iterable<?>, β <: Object, α <: List<β> } describes a proper upper bound for each of α and β, along with a dependency between them.
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ConstraintFormulaTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ConstraintFormulaTest.java
index 0563ca5..3e78bb2 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ConstraintFormulaTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/ConstraintFormulaTest.java
@@ -10,12 +10,12 @@
 import com.github.javaparser.symbolsolver.resolution.typeinference.ConstraintFormula;
 import com.github.javaparser.symbolsolver.resolution.typeinference.InferenceVariable;
 import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.mock;
 
-public class ConstraintFormulaTest {
+class ConstraintFormulaTest {
 
     private TypeSolver typeSolver = new ReflectionTypeSolver();
     private ResolvedType stringType = new ReferenceTypeImpl(new ReflectionTypeSolver().solveType(String.class.getCanonicalName()), typeSolver);
@@ -27,7 +27,7 @@
      * Through reduction, this will become the constraint formula: ‹String <: α›.
      */
     @Test
-    public void testExpressionCompatibleWithTypeReduce1() {
+    void testExpressionCompatibleWithTypeReduce1() {
         ResolvedTypeParameterDeclaration tp = mock(ResolvedTypeParameterDeclaration.class);
 
         Expression e = new StringLiteralExpr("hi");
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedPrimitiveTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedPrimitiveTypeTest.java
new file mode 100644
index 0000000..6dd1762
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedPrimitiveTypeTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.types;
+
+import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
+import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class ResolvedPrimitiveTypeTest extends AbstractResolutionTest {
+
+    @Test
+    void byNameValidOptions() {
+        assertEquals(ResolvedPrimitiveType.BOOLEAN, ResolvedPrimitiveType.byName("boolean"));
+        assertEquals(ResolvedPrimitiveType.CHAR, ResolvedPrimitiveType.byName("char"));
+        assertEquals(ResolvedPrimitiveType.BYTE, ResolvedPrimitiveType.byName("byte"));
+        assertEquals(ResolvedPrimitiveType.SHORT, ResolvedPrimitiveType.byName("short"));
+        assertEquals(ResolvedPrimitiveType.INT, ResolvedPrimitiveType.byName("int"));
+        assertEquals(ResolvedPrimitiveType.LONG, ResolvedPrimitiveType.byName("long"));
+        assertEquals(ResolvedPrimitiveType.FLOAT, ResolvedPrimitiveType.byName("float"));
+        assertEquals(ResolvedPrimitiveType.DOUBLE, ResolvedPrimitiveType.byName("double"));
+    }
+
+    @Test
+    void byNameInValidOptions() {
+        assertThrows(IllegalArgumentException.class, () -> ResolvedPrimitiveType.byName("unexisting"));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolverTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolverTest.java
index b9be968..b13cedb 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolverTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/AarTypeSolverTest.java
@@ -16,20 +16,20 @@
 
 package com.github.javaparser.symbolsolver.resolution.typesolvers;
 
-import com.github.javaparser.symbolsolver.AbstractTest;
-import org.junit.Test;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import org.junit.jupiter.api.Test;
 
-import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class AarTypeSolverTest extends AbstractTest {
+class AarTypeSolverTest extends AbstractSymbolResolutionTest {
 
     @Test
-    public void initial() throws IOException {
-        String pathToJar = adaptPath("src/test/resources/aars/support-compat-24.2.0.aar");
-        AarTypeSolver aarTypeSolver = new AarTypeSolver(new File(pathToJar));
+    void initial() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/aars/support-compat-24.2.0.aar");
+        AarTypeSolver aarTypeSolver = new AarTypeSolver(pathToJar);
         assertEquals(true, aarTypeSolver.tryToSolveType("android.support.v4.app.ActivityCompat").isSolved());
         assertEquals(true, aarTypeSolver.tryToSolveType("android.support.v4.app.ActivityManagerCompat").isSolved());
         assertEquals(true, aarTypeSolver.tryToSolveType("android.support.v4.app.NotificationCompat").isSolved());
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolverTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolverTest.java
new file mode 100644
index 0000000..affa0d0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolverTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver.ExceptionHandlers;
+
+class CombinedTypeSolverTest {
+
+    static List<Object[]> parameters() {
+        // Why these classes? NFE is a subclass, IOOBE is a superclass and ISE is a class without children (by default)
+        Predicate<Exception> whitelistTestFilter = ExceptionHandlers.getTypeBasedWhitelist(NumberFormatException.class,
+                IndexOutOfBoundsException.class, IllegalStateException.class);
+        Predicate<Exception> blacklistTestFilter = ExceptionHandlers.getTypeBasedBlacklist(NumberFormatException.class,
+                IndexOutOfBoundsException.class, IllegalStateException.class);
+
+        return Arrays.asList(new Object[][] {
+                { new RuntimeException(), ExceptionHandlers.IGNORE_ALL, true }, // 0
+                { new RuntimeException(), ExceptionHandlers.IGNORE_NONE, false }, // 1
+
+                { new RuntimeException(), whitelistTestFilter, false }, // 2
+                { new IllegalStateException(), whitelistTestFilter, true }, // 3
+
+                { new NumberFormatException(), whitelistTestFilter, true }, // 4
+                { new IllegalArgumentException(), whitelistTestFilter, false }, // 5
+
+                { new IndexOutOfBoundsException(), whitelistTestFilter, true }, // 6
+                { new ArrayIndexOutOfBoundsException(), whitelistTestFilter, true }, // 7
+
+                { new RuntimeException(), blacklistTestFilter, true }, // 8
+                { new NullPointerException(), blacklistTestFilter, true }, // 9
+                { new IllegalStateException(), blacklistTestFilter, false }, // 10
+
+                { new NumberFormatException(), blacklistTestFilter, false }, // 11
+                { new IllegalArgumentException(), blacklistTestFilter, true }, // 12
+
+                { new IndexOutOfBoundsException(), blacklistTestFilter, false }, // 13
+                { new ArrayIndexOutOfBoundsException(), blacklistTestFilter, false }, // 14
+        });
+    }
+
+    @ParameterizedTest
+    @MethodSource("parameters")
+    void testExceptionFilter(Exception toBeThrownException, Predicate<Exception> filter, boolean expectForward) {
+        TypeSolver erroringTypeSolver = mock(TypeSolver.class);
+        doThrow(toBeThrownException).when(erroringTypeSolver).tryToSolveType(any(String.class));
+
+        TypeSolver secondaryTypeSolver = mock(TypeSolver.class);
+        when(secondaryTypeSolver.tryToSolveType(any(String.class)))
+                .thenReturn(SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class));
+
+        try {
+            new CombinedTypeSolver(filter, erroringTypeSolver, secondaryTypeSolver)
+                    .tryToSolveType("an uninteresting string");
+            assertTrue(expectForward, "Forwarded, but we expected an exception");
+        } catch (Exception e) {
+            assertFalse(expectForward, "Exception, but we expected forwarding"); // if we expected the error to be
+            // forwarded there shouldn't be an
+            // exception
+        }
+
+        verify(secondaryTypeSolver, times(expectForward ? 1 : 0)).tryToSolveType(any(String.class));
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolverTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolverTest.java
index 346fcfd..fa11073 100644
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolverTest.java
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolverTest.java
@@ -16,19 +16,25 @@
 
 package com.github.javaparser.symbolsolver.resolution.typesolvers;
 
-import com.github.javaparser.symbolsolver.AbstractTest;
-import org.junit.Test;
+import com.github.javaparser.resolution.UnsolvedSymbolException;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 
-public class JarTypeSolverTest extends AbstractTest {
+class JarTypeSolverTest extends AbstractSymbolResolutionTest {
 
     @Test
-    public void initial() throws IOException {
-        String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
+    void initial() throws IOException {
+        Path pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
         JarTypeSolver jarTypeSolver = new JarTypeSolver(pathToJar);
         assertEquals(true, jarTypeSolver.tryToSolveType("com.github.javaparser.SourcesHelper").isSolved());
         assertEquals(true, jarTypeSolver.tryToSolveType("com.github.javaparser.Token").isSolved());
@@ -38,4 +44,43 @@
         assertEquals(false, jarTypeSolver.tryToSolveType("Foo").isSolved());
     }
 
+    @Test
+    void dependenciesBetweenJarsNotTriggeringReferences() throws IOException {
+        Path pathToJar1 = adaptPath("src/test/resources/jar1.jar");
+        JarTypeSolver jarTypeSolver1 = new JarTypeSolver(pathToJar1);
+        assertEquals(true, jarTypeSolver1.tryToSolveType("foo.bar.A").isSolved());
+
+        Path pathToJar2 = adaptPath("src/test/resources/jar2.jar");
+        JarTypeSolver jarTypeSolver2 = new JarTypeSolver(pathToJar2);
+        assertEquals(true, jarTypeSolver2.tryToSolveType("foo.zum.B").isSolved());
+
+
+    }
+
+    @Test
+    void dependenciesBetweenJarsTriggeringReferencesThatCannotBeResolved() throws IOException {
+        assertThrows(UnsolvedSymbolException.class, () -> {
+            Path pathToJar2 = adaptPath("src/test/resources/jar2.jar");
+        JarTypeSolver jarTypeSolver2 = new JarTypeSolver(pathToJar2);
+        ResolvedReferenceTypeDeclaration b = jarTypeSolver2.tryToSolveType("foo.zum.B").getCorrespondingDeclaration();
+        b.getAncestors();
+    });
+        
+        }
+
+    @Test
+    void dependenciesBetweenJarsTriggeringReferencesThatCanBeResolved() throws IOException {
+        Path pathToJar1 = adaptPath("src/test/resources/jar1.jar");
+        JarTypeSolver jarTypeSolver1 = new JarTypeSolver(pathToJar1);
+
+        Path pathToJar2 = adaptPath("src/test/resources/jar2.jar");
+        JarTypeSolver jarTypeSolver2 = new JarTypeSolver(pathToJar2);
+
+        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(jarTypeSolver1, jarTypeSolver2);
+
+        ResolvedReferenceTypeDeclaration b = combinedTypeSolver.tryToSolveType("foo.zum.B").getCorrespondingDeclaration();
+        List<ResolvedReferenceType> ancestors = b.getAncestors();
+        assertEquals(1, ancestors.size());
+    }
+
 }
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolverTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolverTest.java
new file mode 100644
index 0000000..4eef475
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolverTest.java
@@ -0,0 +1,45 @@
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.utils.LeanParserConfiguration;
+import com.github.javaparser.utils.CodeGenerationUtils;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junitpioneer.jupiter.TempDirectory;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class JavaParserTypeSolverTest {
+
+    @Disabled
+    @Test
+    void containsLocationInStorage() {
+        JavaParserTypeSolver typeSolver = new JavaParserTypeSolver(CodeGenerationUtils.mavenModuleRoot(JavaParserTypeSolver.class).resolve("src/main/java"), new LeanParserConfiguration());
+
+        SymbolReference<ResolvedReferenceTypeDeclaration> x = typeSolver.tryToSolveType("com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver");
+
+        JavaParserClassDeclaration declaration = (JavaParserClassDeclaration) x.getCorrespondingDeclaration();
+        Node wrappedNode = declaration.getWrappedNode();
+        assertEquals("JavaParserTypeSolver.java", wrappedNode.findCompilationUnit().get().getStorage().get().getFileName());
+    }
+
+    @Test
+    @ExtendWith(TempDirectory.class)
+    void folderTraversalDoesNotKeepFolderHandlesHostage(@TempDirectory.TempDir Path tempDir) throws IOException {
+        File folder = tempDir.resolve("folder").toFile();
+        assertTrue(folder.mkdirs());
+        File testJava = new File(folder, "Test.java");
+        assertTrue(testJava.createNewFile());
+        JavaParserTypeSolver typeSolver = new JavaParserTypeSolver(folder.getParentFile());
+        typeSolver.tryToSolveType("folder.Test");
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolverTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolverTest.java
new file mode 100644
index 0000000..eeb3700
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolverTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ReflectionTypeSolverTest extends AbstractSymbolResolutionTest {
+
+    @Test
+    void testHasType() {
+        ReflectionTypeSolver ts = new ReflectionTypeSolver();
+        assertEquals(true, ts.hasType(String.class.getCanonicalName()));
+        assertEquals(true, ts.hasType(Object.class.getCanonicalName()));
+        assertEquals(false, ts.hasType("foo.zum.unexisting"));
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/SomeClass.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/SomeClass.java
new file mode 100644
index 0000000..452af7f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/SomeClass.java
@@ -0,0 +1,8 @@
+package com.github.javaparser.symbolsolver.testingclasses;
+
+public class SomeClass {
+
+    public enum InnerEnum {
+        CONSTANT
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/UtilityClass.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/UtilityClass.java
new file mode 100644
index 0000000..df8af3c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/testingclasses/UtilityClass.java
@@ -0,0 +1,7 @@
+package com.github.javaparser.symbolsolver.testingclasses;
+
+public class UtilityClass {
+    public static void method(SomeClass.InnerEnum e) {
+
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/LeanParserConfiguration.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/LeanParserConfiguration.java
new file mode 100644
index 0000000..eb2801a
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/LeanParserConfiguration.java
@@ -0,0 +1,12 @@
+package com.github.javaparser.symbolsolver.utils;
+
+import com.github.javaparser.ParserConfiguration;
+
+public class LeanParserConfiguration extends ParserConfiguration {
+    public LeanParserConfiguration() {
+        setLanguageLevel(ParserConfiguration.LanguageLevel.RAW);
+        setStoreTokens(false);
+        setAttributeComments(false);
+        setLexicalPreservationEnabled(false);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategyTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategyTest.java
new file mode 100644
index 0000000..21f2770
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverCollectionStrategyTest.java
@@ -0,0 +1,44 @@
+package com.github.javaparser.symbolsolver.utils;
+
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.utils.Log;
+import com.github.javaparser.utils.ProjectRoot;
+import com.github.javaparser.utils.SourceRoot;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static com.github.javaparser.utils.CodeGenerationUtils.classLoaderRoot;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class SymbolSolverCollectionStrategyTest {
+
+    private final Path root = classLoaderRoot(SymbolSolverCollectionStrategyTest.class).resolve("../../../javaparser-core").normalize();
+    private final ProjectRoot projectRoot = new SymbolSolverCollectionStrategy().collect(root);
+
+    @Test
+    void resolveExpressions() throws IOException {
+        SourceRoot sourceRoot = projectRoot.getSourceRoot(root.resolve("src/main/java")).get();
+        AtomicInteger unresolved = new AtomicInteger();
+        for (ParseResult<CompilationUnit> parseResult : sourceRoot.tryToParse()) {
+            parseResult.ifSuccessful(compilationUnit -> {
+                for (MethodDeclaration expr : compilationUnit.findAll(MethodDeclaration.class)) {
+                    try {
+                        expr.resolve().getQualifiedSignature();
+                    } catch (UnsupportedOperationException e) {
+                        // not supported operation, just skip
+                    } catch (Exception e) {
+                        unresolved.getAndIncrement();
+                        Log.error(e, "Unable to resolve %s from %s", () -> expr, () -> compilationUnit.getStorage().get().getPath());
+                    }
+                }
+            });
+        }
+        // not too many MethodDeclarations should be unresolved
+        assertTrue(unresolved.get() < 10);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverQuickSetupTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverQuickSetupTest.java
deleted file mode 100644
index ddc1bc6..0000000
--- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/utils/SymbolSolverQuickSetupTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.github.javaparser.symbolsolver.utils;
-
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.symbolsolver.JavaSymbolSolver;
-import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
-import com.github.javaparser.utils.SourceRoot;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-
-/**
- * Try to resolve all the ClassOrInterfaceDeclaration and MethodCallExpr in some resources folder. If it fails to do
- * so, an IllegalStateException is thrown.
- */
-public class SymbolSolverQuickSetupTest {
-
-    private Path root = Paths.get("src/test/resources/symbolsolver_quicksetup");
-    private ParserConfiguration parserConfiguration = new ParserConfiguration();
-
-    @Before
-    public void setUp() throws IOException {
-        SymbolSolverQuickSetup ssr = new SymbolSolverQuickSetup(root);
-        TypeSolver typeSolver = ssr.walk();
-
-        parserConfiguration.setSymbolResolver(new JavaSymbolSolver(typeSolver));
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void notResolve() throws IOException {
-        SourceRoot sourceRoot = new SourceRoot(root);
-        sourceRoot.tryToParse();
-        // try to resolve, this will fail
-        sourceRoot.getCompilationUnits().forEach(compilationUnit ->
-                compilationUnit.findAll(ClassOrInterfaceDeclaration.class).forEach(ClassOrInterfaceDeclaration::resolve));
-    }
-
-    @Test
-    public void resolve() throws IOException {
-        SourceRoot sourceRoot = new SourceRoot(root, parserConfiguration);
-        sourceRoot.tryToParse();
-        // try to resolve, this should succeed
-        sourceRoot.getCompilationUnits().forEach(compilationUnit ->
-                compilationUnit.findAll(ClassOrInterfaceDeclaration.class).forEach(ClassOrInterfaceDeclaration::resolve));
-    }
-}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt b/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt
index 910777b..945aa61 100644
--- a/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt
+++ b/javaparser-symbol-solver-testing/src/test/resources/Annotations.java.txt
@@ -1,18 +1,32 @@
 package foo.bar;
 
+import java.lang.annotation.*;
+import org.junit.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
 public @interface MyAnnotation {
 }
 
 public @interface MyAnnotation2 {
 }
 
-public @interface MyAnnotationWithFields {
-    int field();
+public @interface MyAnnotationWithSingleValue {
+    int value();
+}
+
+public @interface MyAnnotationWithElements {
+    int num();
+    String str();
 }
 
 @MyAnnotation
 class CA {
+    @Override
+    public boolean equals(Object o) { return true; }
 
+    @Before
+    public void setUp() {}
 }
 
 @MyAnnotation2
@@ -20,3 +34,14 @@
 
 }
 
+@MyAnnotationWithSingleValue(42)
+class CC {
+    public boolean foo(Object o) { @SuppressWarnings("unchecked") String s = (String) o; }
+
+    @Ignore("lalala") @Test public void testSomething() {}
+}
+
+@MyAnnotationWithElements(num = 42, str = "test")
+class CD {
+    @Test(expected = Throwable.class, timeout = 42L) public void testSomethingElse() {}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/AnonymousClassDeclarations.java.txt b/javaparser-symbol-solver-testing/src/test/resources/AnonymousClassDeclarations.java.txt
index f994225..5274a63 100644
--- a/javaparser-symbol-solver-testing/src/test/resources/AnonymousClassDeclarations.java.txt
+++ b/javaparser-symbol-solver-testing/src/test/resources/AnonymousClassDeclarations.java.txt
@@ -68,4 +68,8 @@
         });
     }
 
+    void fooBar6() {
+        new DoFn.ProcessContext() {}.innerClassMethod();
+    }
+
 }
diff --git a/javaparser-symbol-solver-testing/src/test/resources/AnonymousClassMethodClass.java.txt b/javaparser-symbol-solver-testing/src/test/resources/AnonymousClassMethodClass.java.txt
new file mode 100644
index 0000000..fb02c48
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/AnonymousClassMethodClass.java.txt
@@ -0,0 +1,14 @@
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+
+public class AnonymousClassExample {
+    private static final Integer f = 1;
+    private void sentNotificationResultEventInTransaction() {
+        new TransactionCallbackWithoutResult() {
+            @Override
+            protected void doInTransactionWithoutResult(TransactionStatus status) {
+                f.toString();
+            }
+        };
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/ClassExtendingUnknownClass.java.txt b/javaparser-symbol-solver-testing/src/test/resources/ClassExtendingUnknownClass.java.txt
new file mode 100644
index 0000000..1dc2533
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/ClassExtendingUnknownClass.java.txt
@@ -0,0 +1,20 @@
+import com.third.party.library.UnknownClass;
+
+public class ClassExtendingUnknownClass extends UnknownClass {
+
+    private int foo;
+
+    public int getFoo() {
+        return foo;
+    }
+
+    public int getFoo2() {
+        return this.foo;
+    }
+
+    public void foo(String s) {
+        bar(s);
+    }
+
+    public void bar(String s) {}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/ClassWithAnnotationAncestor.java.txt b/javaparser-symbol-solver-testing/src/test/resources/ClassWithAnnotationAncestor.java.txt
new file mode 100644
index 0000000..b0d2ba8
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/ClassWithAnnotationAncestor.java.txt
@@ -0,0 +1,16 @@
+public class ClassWithAnnotationAncestor implements SuppressWarnings {
+
+    public String testMethod() {
+        return "result";
+    }
+
+    @Override
+    public String[] value() {
+        return new String[0];
+    }
+
+    @Override
+    public Class<? extends Annotation> annotationType() {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/ComplexTypeResolving.java.txt b/javaparser-symbol-solver-testing/src/test/resources/ComplexTypeResolving.java.txt
new file mode 100644
index 0000000..2bcdbba
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/ComplexTypeResolving.java.txt
@@ -0,0 +1,23 @@
+public class Main {
+	public class ResolveMe {
+		public String s = "correct";
+	}
+
+	class Child extends ParentClass {
+		void foo() {
+			ResolveMe x = new ResolveMe();
+		}
+	}
+}
+
+class ParentClass extends SuperParentClass {
+	private class ResolveMe {
+		public String s = "incorrect";
+	}
+}
+
+class SuperParentClass {
+	public class ResolveMe {
+		public String s = "also incorrect";
+	}
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/ConstructorCalls.java.txt b/javaparser-symbol-solver-testing/src/test/resources/ConstructorCalls.java.txt
new file mode 100644
index 0000000..429f9a6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/ConstructorCalls.java.txt
@@ -0,0 +1,34 @@
+class ConstructorCalls {
+
+    void testNormalConstructor() {
+        new OtherClass();
+    }
+
+    void testInnerClassConstructor() {
+        OtherClass oc = new OtherClass();
+        oc.new InnerClass();
+    }
+
+    void testInnerClassConstructorWithNewScope() {
+        new OtherClass().new InnerClass();
+    }
+
+    void testInnerInnerClassConstructor() {
+        new OtherClass().new InnerClass().new InnerInnerClass();
+    }
+}
+
+class OtherClass {
+
+    OtherClass() {}
+
+    class InnerClass {
+
+        InnerClass() {}
+
+        class InnerInnerClass {
+
+            InnerInnerClass() {}
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/ConstructorCallsEnum.java.txt b/javaparser-symbol-solver-testing/src/test/resources/ConstructorCallsEnum.java.txt
new file mode 100644
index 0000000..421b9dd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/ConstructorCallsEnum.java.txt
@@ -0,0 +1,10 @@
+public enum ConstructorCallsEnum {
+    ONE(1),
+    TWO(2);
+
+    private final int i;
+
+    ConstructorCallsEnum(int i) {
+        this.i = i;
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/EnumFieldAccess.java.txt b/javaparser-symbol-solver-testing/src/test/resources/EnumFieldAccess.java.txt
new file mode 100644
index 0000000..eb1e14d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/EnumFieldAccess.java.txt
@@ -0,0 +1,9 @@
+class EnumFieldAccess {
+    public enum MyEnum {
+        SOME, ARBITRARY, VALUES
+    }
+
+    public MyEnum accessField() {
+        return MyEnum.SOME;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/GenericArrayMethodArgument.java.txt b/javaparser-symbol-solver-testing/src/test/resources/GenericArrayMethodArgument.java.txt
new file mode 100644
index 0000000..1a4bb10
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/GenericArrayMethodArgument.java.txt
@@ -0,0 +1,12 @@
+class GenericArrayMethodArgument {
+
+    static class Foo<T> {
+        public void foo(T[] array) {}
+    }
+
+    public void bar() {
+        Foo<String> foo = new Foo<>();
+        foo.foo(new String[1]);
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/GenericClassNavigator.java.txt b/javaparser-symbol-solver-testing/src/test/resources/GenericClassNavigator.java.txt
new file mode 100644
index 0000000..cbfae72
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/GenericClassNavigator.java.txt
@@ -0,0 +1,31 @@
+import javaparser.GenericClass;
+
+import java.util.List;
+
+public class GenericClassNavigator {
+
+    public static void doubleTyped() {
+        new GenericClass().genericMethodWithDoubleTypedReturnType();
+    }
+
+    public static void nestedTyped() {
+        new GenericClass().genericMethodWithNestedReturnType();
+    }
+
+    public static void simple() {
+        new GenericClass<List<List<String>>>().get();
+    }
+
+    public static void input() {
+        GenericClass.copy(new GenericClass<List<String>>());
+    }
+
+    public void complex() {
+        new GenericClass().complexGenerics();
+    }
+
+    public void nestedTypes() {
+        GenericClass.asList(GenericClass.Bar.CONSTANT);
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/GenericsWildcard.java.txt b/javaparser-symbol-solver-testing/src/test/resources/GenericsWildcard.java.txt
new file mode 100644
index 0000000..02cd1ab
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/GenericsWildcard.java.txt
@@ -0,0 +1,19 @@
+import java.util.Map;
+
+public class GenericsWildcard {
+
+    public static class Foo {
+        public String bar() {
+            return "";
+        }
+    }
+
+    public String unbounded(Map<String, ?> map) {
+        return map.get("").toString();
+    }
+
+    public String bounded(Map<String, ? extends Foo> map) {
+        return map.get("").bar();
+    }
+
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/Issue1482.java.txt b/javaparser-symbol-solver-testing/src/test/resources/Issue1482.java.txt
new file mode 100644
index 0000000..8ee78a3
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/Issue1482.java.txt
@@ -0,0 +1,13 @@
+public class MultiCatchMethodCallExpr {
+	public void test() {
+		try {
+			methodWithExceptions();
+		} catch (ArrayIndexOutOfBoundsException | ClassCastException e) {
+			System.out.println(e.getMessage());
+		}
+	}
+	
+	private void methodWithExceptions() throws ArrayIndexOutOfBoundsException, ClassCastException {
+		// do something
+	}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/Issue2258.java.txt b/javaparser-symbol-solver-testing/src/test/resources/Issue2258.java.txt
new file mode 100755
index 0000000..bb18a72
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/Issue2258.java.txt
@@ -0,0 +1,11 @@
+

+public class Issue2258 {

+

+	public static void foo(Object[] nullable) {

+		System.out.println("Verify program execution."); // This line is not necessary.

+	}

+

+	public static void main(String[] args) {

+		Issue2258.foo(null);

+	}

+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/Lambda.java.txt b/javaparser-symbol-solver-testing/src/test/resources/Lambda.java.txt
index 6e0cbde..2b3ba36 100644
--- a/javaparser-symbol-solver-testing/src/test/resources/Lambda.java.txt
+++ b/javaparser-symbol-solver-testing/src/test/resources/Lambda.java.txt
@@ -6,6 +6,10 @@
 	String process(String value);
 }
 
+public interface Processor {
+	void process(String value);
+}
+
 public class Agenda {
 	
 	Lambda functional = p -> p.toLowerCase();
@@ -29,6 +33,14 @@
         return 0;
     }
 
+    public void print(String value) {
+        return process(value, v -> System.out.println(v));
+    }
+
+    private void process(String value, Processor a) {
+        a.process(value);
+    }
+
     public double bifunc(){
         return test((x,y) -> String.valueOf(func(x,y)));
     }
diff --git a/javaparser-symbol-solver-testing/src/test/resources/MethodLikeSignaturesTest.java.txt b/javaparser-symbol-solver-testing/src/test/resources/MethodLikeSignaturesTest.java.txt
new file mode 100644
index 0000000..5cc335a
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/MethodLikeSignaturesTest.java.txt
@@ -0,0 +1,9 @@
+import java.io.File;
+
+class MethodLikeSignaturesTest {
+
+	public void foo() {
+		File file = new File("somepath");
+		file.delete();
+	}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/NestedClasses.java.txt b/javaparser-symbol-solver-testing/src/test/resources/NestedClasses.java.txt
new file mode 100644
index 0000000..956acfc
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/NestedClasses.java.txt
@@ -0,0 +1,13 @@
+class A extends X.Y {
+
+	void foo() {
+		X.Y xy = null;
+		xy.bar();
+	}
+}
+
+class X {
+	static class Y {
+		void bar() {}
+	}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/NestedInterfaces.java.txt b/javaparser-symbol-solver-testing/src/test/resources/NestedInterfaces.java.txt
new file mode 100644
index 0000000..577eb6f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/NestedInterfaces.java.txt
@@ -0,0 +1,13 @@
+interface A extends X.Y {
+
+	default void foo() {
+		X.Y xy = null;
+		xy.bar();
+	}
+}
+
+interface X {
+	interface Y {
+		void bar();
+	}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/NestedInterfacesWithIdenticalNames.java.txt b/javaparser-symbol-solver-testing/src/test/resources/NestedInterfacesWithIdenticalNames.java.txt
new file mode 100644
index 0000000..ef60a5a
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/NestedInterfacesWithIdenticalNames.java.txt
@@ -0,0 +1,13 @@
+interface A extends X.A {
+
+	default void foo() {
+		X.A xa = null;
+		xa.bar();
+	}
+}
+
+interface X {
+	interface A {
+		void bar();
+	}
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/NotQuiteCyclicParent.java.txt b/javaparser-symbol-solver-testing/src/test/resources/NotQuiteCyclicParent.java.txt
new file mode 100644
index 0000000..e1f8305
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/NotQuiteCyclicParent.java.txt
@@ -0,0 +1,7 @@
+package foo;
+
+public interface NotQuiteCyclicParent extends bar.NotQuiteCyclicParent {
+    default void main() {
+        MyType x = new MyType();
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethodCall.java.txt b/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethodCall.java.txt
new file mode 100644
index 0000000..094832c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethodCall.java.txt
@@ -0,0 +1,12 @@
+package test;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.visitor.GenericVisitor;
+import com.github.javaparser.ast.visitor.VoidVisitor;
+
+public class OverloadedMethodCall {
+    public void foo(Node node) {
+        node.accept((GenericVisitor) null, null);
+        node.accept((VoidVisitor) null, null);
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethods.java.txt b/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethods.java.txt
index fef317a..4d5bd10 100644
--- a/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethods.java.txt
+++ b/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethods.java.txt
@@ -24,4 +24,32 @@
         Object o = null;
         overloaded(o);
     }
+
+    public void complexOverloading1(String... s) {}
+    public void complexOverloading1(String s1, String s2) {}
+
+    public void testComplex1() {
+        complexOverloading1("a", "b");
+    }
+
+    public void complexOverloading2(String... s) {}
+    public void complexOverloading2(String s1, String s2, Object s3) {}
+
+    public void testComplex2() {
+        complexOverloading2("a", "b");
+    }
+
+    public void complexOverloading3(Integer i) {}
+    public void complexOverloading3(long l) {}
+
+    public void testComplex3() {
+        complexOverloading3(1);
+    }
+
+    public void complexOverloading4(long l, int i) {}
+    public void complexOverloading4(int i, int... is) {}
+
+    public void testComplex4() {
+        complexOverloading4(1, 2);
+    }
 }
diff --git a/javaparser-symbol-solver-testing/src/test/resources/PlatformTestUtil.java.txt b/javaparser-symbol-solver-testing/src/test/resources/PlatformTestUtil.java.txt
new file mode 100644
index 0000000..0f740fb
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/PlatformTestUtil.java.txt
@@ -0,0 +1,135 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.testFramework;
+
+import com.intellij.configurationStore.StateStorageManagerKt;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.process.ProcessIOExecutorService;
+import com.intellij.execution.process.ProcessOutput;
+import com.intellij.execution.util.ExecUtil;
+import com.intellij.ide.DataManager;
+import com.intellij.ide.IdeEventQueue;
+import com.intellij.ide.fileTemplates.FileTemplateManager;
+import com.intellij.ide.fileTemplates.impl.FileTemplateManagerImpl;
+import com.intellij.ide.util.treeView.AbstractTreeBuilder;
+import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.ide.util.treeView.AbstractTreeStructure;
+import com.intellij.ide.util.treeView.AbstractTreeUi;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ex.ActionUtil;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.impl.ApplicationImpl;
+import com.intellij.openapi.application.impl.LaterInvocator;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.extensions.*;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
+import com.intellij.openapi.fileTypes.FileTypes;
+import com.intellij.openapi.paths.WebReference;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ex.ProjectManagerEx;
+import com.intellij.openapi.ui.Queryable;
+import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileFilter;
+import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
+import com.intellij.psi.PsiReference;
+import com.intellij.rt.execution.junit.FileComparisonFailure;
+import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy;
+import com.intellij.ui.tree.AsyncTreeModel;
+import com.intellij.util.*;
+import com.intellij.util.concurrency.AppExecutorUtil;
+import com.intellij.util.concurrency.AppScheduledExecutorService;
+import com.intellij.util.io.Decompressor;
+import com.intellij.util.lang.JavaVersion;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.tree.TreeUtil;
+import gnu.trove.Equality;
+import junit.framework.AssertionFailedError;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.concurrency.AsyncPromise;
+import org.jetbrains.concurrency.Promise;
+
+import javax.swing.*;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+import java.awt.event.InvocationEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.*;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.intellij.openapi.application.ApplicationManager.getApplication;
+import static org.junit.Assert.*;
+
+/**
+ * @author yole
+ */
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "TestOnlyProblems"})
+public class PlatformTestUtil {
+  public static <T> void assertComparisonContractNotViolated(@NotNull List<? extends T> values,
+                                                             @NotNull Comparator<? super T> comparator,
+                                                             @NotNull Equality<? super T> equality) {
+    for (int i1 = 0; i1 < values.size(); i1++) {
+      for (int i2 = i1; i2 < values.size(); i2++) {
+        T value1 = values.get(i1);
+        T value2 = values.get(i2);
+
+        int result12 = comparator.compare(value1, value2);
+        int result21 = comparator.compare(value2, value1);
+        if (equality.equals(value1, value2)) {
+          assertEquals(String.format("Equal, but not 0: '%s' - '%s'", value1, value2), 0, result12);
+          assertEquals(String.format("Equal, but not 0: '%s' - '%s'", value2, value1), 0, result21);
+        }
+        else {
+          if (result12 == 0) fail(String.format("Not equal, but 0: '%s' - '%s'", value1, value2));
+          if (result21 == 0) fail(String.format("Not equal, but 0: '%s' - '%s'", value2, value1));
+          if (Integer.signum(result12) == Integer.signum(result21)) {
+            fail(String.format("Not symmetrical: '%s' - '%s'", value1, value2));
+          }
+        }
+
+        for (int i3 = i2; i3 < values.size(); i3++) {
+          T value3 = values.get(i3);
+
+          int result23 = comparator.compare(value2, value3);
+          int result31 = comparator.compare(value3, value1);
+
+          if (!isTransitive(result12, result23, result31)) {
+            fail(String.format("Not transitive: '%s' - '%s' - '%s'", value1, value2, value3));
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/ReflectionTypeSolverConstructorResolution.java.txt b/javaparser-symbol-solver-testing/src/test/resources/ReflectionTypeSolverConstructorResolution.java.txt
new file mode 100644
index 0000000..e586c4b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/ReflectionTypeSolverConstructorResolution.java.txt
@@ -0,0 +1,7 @@
+package java.lang;
+
+public class ReflectionTypeSolverConstructionResolution extends AbstractStringBuilder {
+    public ReflectionTypeSolverConstructionResolution(int i) {
+        super(i);
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/ReflectionTypeSolverFieldFromInterfaceResolution.java.txt b/javaparser-symbol-solver-testing/src/test/resources/ReflectionTypeSolverFieldFromInterfaceResolution.java.txt
new file mode 100644
index 0000000..dbe5839
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/ReflectionTypeSolverFieldFromInterfaceResolution.java.txt
@@ -0,0 +1,7 @@
+import javax.swing.JDialog;
+
+public class Test {
+    public int foo() {
+        return JDialog.DISPOSE_ON_CLOSE;
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/TryInSwitch.java.txt b/javaparser-symbol-solver-testing/src/test/resources/TryInSwitch.java.txt
new file mode 100644
index 0000000..aee824f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/TryInSwitch.java.txt
@@ -0,0 +1,20 @@
+import java.io.File;

+

+class TryInSwitch {

+

+	public void foo() {

+		int i = 42;

+

+		switch (i) {

+			default:

+				File file;

+				try {

+					file = new File("...");

+					file.delete();

+				} catch (Exception e) {

+					// ...

+				}

+				break;

+		}

+	}

+}

diff --git a/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/A.java b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/A.java
new file mode 100644
index 0000000..3df88a8
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/A.java
@@ -0,0 +1,7 @@
+package extends_duplicate;
+
+public class A extends DuplicateTypeName {
+    class DuplicateTypeName extends A {
+
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/DuplicateTypeName.java b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/DuplicateTypeName.java
new file mode 100644
index 0000000..7f485cb
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/DuplicateTypeName.java
@@ -0,0 +1,5 @@
+package extends_duplicate;
+
+public abstract class DuplicateTypeName {
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/A.java b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/A.java
new file mode 100644
index 0000000..14d2fb0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/A.java
@@ -0,0 +1,7 @@
+package implements_duplicate;
+
+public class A implements DuplicateTypeName {
+    class DuplicateTypeName extends A {
+
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/DuplicateTypeName.java b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/DuplicateTypeName.java
new file mode 100644
index 0000000..1b6a756
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/DuplicateTypeName.java
@@ -0,0 +1,5 @@
+package implements_duplicate;
+
+public interface DuplicateTypeName {
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/UnknownMethods.java.txt b/javaparser-symbol-solver-testing/src/test/resources/UnknownMethods.java.txt
new file mode 100644
index 0000000..ebd92d1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/UnknownMethods.java.txt
@@ -0,0 +1,16 @@
+package testcase;

+

+import java.io.IOException;

+import javax.servlet.http.*;

+

+public abstract class UnknownMethods extends HttpServlet {

+

+	public void test1(HttpServletRequest request, HttpServletResponse response) throws IOException {

+		response.getWriter().println("hello world!");

+	}

+

+	public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {

+		String data = "world!";

+		response.getWriter().println("hello " + data);

+	}

+}

diff --git a/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/AClass.java b/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/AClass.java
new file mode 100644
index 0000000..126cc45
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/AClass.java
@@ -0,0 +1,6 @@
+package foo.bar;
+
+class AClass {
+    static Object field1 = BinaryExpr.Operator.OR;
+    static Object field2 = foo.bar.BinaryExpr.Operator.AND;
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/BinaryExpr.java b/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/BinaryExpr.java
new file mode 100644
index 0000000..c9a09bb
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/BinaryExpr.java
@@ -0,0 +1,11 @@
+package foo.bar;
+
+public interface BinaryExpr {
+
+    enum Operator {
+        OR("||"),
+        AND("&&");
+
+        Operator(String codeRepresentation) { }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/differentpackage/AClass2.java b/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/differentpackage/AClass2.java
new file mode 100644
index 0000000..12ce276
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/enumLiteralsInAnnotatedClass/foo/bar/differentpackage/AClass2.java
@@ -0,0 +1,8 @@
+package foo.bar.differentpackage;
+
+import foo.bar.BinaryExpr;
+
+class AClass {
+    static Object field1 = BinaryExpr.Operator.OR;
+    static Object field2 = foo.bar.BinaryExpr.Operator.AND;
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/enums/EnumWithAncestor.java b/javaparser-symbol-solver-testing/src/test/resources/enums/EnumWithAncestor.java
new file mode 100644
index 0000000..eac2b8c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/enums/EnumWithAncestor.java
@@ -0,0 +1,5 @@
+public enum EnumWithAncestor implements Cloneable {
+
+    PUBLIC, PRIVATE
+
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/AClass.java b/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/AClass.java
new file mode 100644
index 0000000..c140942
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/AClass.java
@@ -0,0 +1,6 @@
+package foo.bar;
+
+class AClass {
+    static Object field1 = AnInterface.ListChangeType.ADDITION;
+    static Object field2 = foo.bar.AnInterface.ListChangeType.ADDITION;
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/AnInterface.java b/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/AnInterface.java
new file mode 100644
index 0000000..6d1a9b1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/AnInterface.java
@@ -0,0 +1,9 @@
+package foo.bar;
+
+public interface AnInterface {
+
+    enum ListChangeType {
+        ADDITION,
+        REMOVAL
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/differentpackage/AClass2.java b/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/differentpackage/AClass2.java
new file mode 100644
index 0000000..6d35735
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/internalClassInInterface/foo/bar/differentpackage/AClass2.java
@@ -0,0 +1,8 @@
+package foo.bar.differentpackage;
+
+import foo.bar.AnInterface;
+
+class AClass {
+    static Object field1 = AnInterface.ListChangeType.ADDITION;
+    static Object field2 = foo.bar.AnInterface.ListChangeType.ADDITION;
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/issue1485/Complex.java b/javaparser-symbol-solver-testing/src/test/resources/issue1485/Complex.java
new file mode 100644
index 0000000..e05f245
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/issue1485/Complex.java
@@ -0,0 +1,27 @@
+public class Complex {
+
+    private double real;
+    private double imaginary;
+
+    Complex(double _real, double _imaginary) {
+        real = _real;
+        imaginary = _imaginary;
+    }
+
+    Complex(String eval) {
+        Complex result = new Complex(0,0);
+        System.out.println(result.getReal()+","+result.getImaginary());
+    }
+
+    public Complex add(Complex arg) {
+        return new Complex(real+arg.getReal(), imaginary+arg.getImaginary());
+    }
+
+    public double getReal() {
+        return real;
+    }
+
+    public double getImaginary() {
+        return imaginary;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/issue1491/A.java b/javaparser-symbol-solver-testing/src/test/resources/issue1491/A.java
new file mode 100644
index 0000000..e673453
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/issue1491/A.java
@@ -0,0 +1,20 @@
+public class A {
+    public int FUNC() {
+        Class<?> cls = null;
+        if (cls == null) return 0;
+        else {
+            B.FUNC3(cls);
+            return 1;
+        }
+    }
+
+    public void FUNC2(Class<?> arg) {
+        return;
+    }
+}
+
+class B {
+    public static void FUNC3(Class<?> arg) {
+        return;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/jar1.jar b/javaparser-symbol-solver-testing/src/test/resources/jar1.jar
new file mode 100644
index 0000000..1112a86
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/jar1.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/resources/jar2.jar b/javaparser-symbol-solver-testing/src/test/resources/jar2.jar
new file mode 100644
index 0000000..1779d6e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/jar2.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Modifier_J9.txt b/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Modifier_J9.txt
deleted file mode 100644
index c17b5bf..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Modifier_J9.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-  Line 32) EnumSet.of(this) ==> java.util.Set.of(E...)
-  Line 36) modifiers.contains(Modifier.PUBLIC) ==> java.util.AbstractCollection.contains(java.lang.Object)
-  Line 38) modifiers.contains(Modifier.PROTECTED) ==> java.util.AbstractCollection.contains(java.lang.Object)
-  Line 40) modifiers.contains(Modifier.PRIVATE) ==> java.util.AbstractCollection.contains(java.lang.Object)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt b/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
deleted file mode 100644
index e69de29..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
+++ /dev/null
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt b/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
deleted file mode 100644
index e69de29..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
+++ /dev/null
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javassist_generics/generics.jar b/javaparser-symbol-solver-testing/src/test/resources/javassist_generics/generics.jar
new file mode 100644
index 0000000..d08b4d4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/javassist_generics/generics.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javassist_generics/javaparser/GenericClass.java b/javaparser-symbol-solver-testing/src/test/resources/javassist_generics/javaparser/GenericClass.java
new file mode 100644
index 0000000..6315ab5
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/javassist_generics/javaparser/GenericClass.java
@@ -0,0 +1,42 @@
+package javaparser;
+
+import java.util.List;
+import java.util.Map;
+
+public class GenericClass<S> {
+
+    public S get() {
+        return null;
+    }
+
+    public <T> List<List<T>> genericMethodWithNestedReturnType() {
+        return null;
+    }
+
+    public <T,V> Map<T,V> genericMethodWithDoubleTypedReturnType() {
+        return null;
+    }
+
+    public static <T> GenericClass<T> copy(GenericClass<T> input) {
+        return null;
+    }
+
+    public static <T extends Object & Foo<? extends T>> T complexGenerics() {
+        return null;
+    }
+
+    public static <T> List<T> asList(T element) {
+        return null;
+    }
+
+    public interface Foo<T> {
+    }
+
+    public interface Bar {
+        public static List<NestedBar> CONSTANT = null;
+
+        public interface NestedBar {
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/C.class b/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/C.class
new file mode 100644
index 0000000..67bcaab
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/C.class
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/C.java b/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/C.java
new file mode 100644
index 0000000..6642b7c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/C.java
@@ -0,0 +1,16 @@
+import java.util.List;
+
+public class C<S> {
+
+    public void methodWithRawParameter(List l) {
+    }
+
+    public void methodWithGenericParameter(List<String> l) {
+    }
+
+    public <T> void genericMethodWithTypeParameter(List<T> l) {
+    }
+
+    public void methodWithTypeParameter(List<S> l) {
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/javassistmethoddecl.jar b/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/javassistmethoddecl.jar
new file mode 100644
index 0000000..fab0d0c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/javassistmethoddecl/javassistmethoddecl.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_SourceFileInfoExtractor.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_SourceFileInfoExtractor.txt
deleted file mode 100644
index 8537d62..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_SourceFileInfoExtractor.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-  Line 100) JavaParserFacade.get(typeSolver).getTypeDeclaration(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 100) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 101) typeDeclaration.isClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isClass()
-  Line 102) out.println("\n[ Class " + typeDeclaration.getQualifiedName() + " ]") ==> java.io.PrintStream.println(java.lang.String)
-  Line 102) typeDeclaration.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 103) typeDeclaration.asClass().getAllSuperClasses() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getAllSuperClasses()
-  Line 103) typeDeclaration.asClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asClass()
-  Line 104) out.println("  superclass: " + sc.getQualifiedName()) ==> java.io.PrintStream.println(java.lang.String)
-  Line 104) sc.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getQualifiedName()
-  Line 106) typeDeclaration.asClass().getAllInterfaces() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getAllInterfaces()
-  Line 106) typeDeclaration.asClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asClass()
-  Line 107) out.println("  interface: " + sc.getQualifiedName()) ==> java.io.PrintStream.println(java.lang.String)
-  Line 107) sc.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getQualifiedName()
-  Line 114) solveTypeDecl((ClassOrInterfaceDeclaration) node) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveTypeDecl(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 116) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 116) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 117) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 118) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 120) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 120) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 122) JavaParserFacade.get(typeSolver).getType(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node)
-  Line 122) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 123) out.println("  Line " + node.getRange().get().begin.line + ") " + node + " ==> " + ref.describe()) ==> java.io.PrintStream.println(java.lang.String)
-  Line 123) node.getRange().get() ==> java.util.Optional.get()
-  Line 123) node.getRange() ==> com.github.javaparser.ast.Node.getRange()
-  Line 123) ref.describe() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.describe()
-  Line 127) err.println(upe.getMessage()) ==> java.io.PrintStream.println(java.lang.String)
-  Line 127) upe.getMessage() ==> java.lang.Throwable.getMessage()
-  Line 131) err.println(re.getMessage()) ==> java.io.PrintStream.println(java.lang.String)
-  Line 131) re.getMessage() ==> java.lang.Throwable.getMessage()
-  Line 140) out.println("  Line " + node.getBegin().get().line + ") " + node + " ==> " + toString((MethodCallExpr) node)) ==> java.io.PrintStream.println(java.lang.String)
-  Line 140) node.getBegin().get() ==> java.util.Optional.get()
-  Line 140) node.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
-  Line 140) toString((MethodCallExpr) node) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.toString(com.github.javaparser.ast.expr.MethodCallExpr)
-  Line 142) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 143) solveMethodCalls(child) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveMethodCalls(com.github.javaparser.ast.Node)
-  Line 149) toString(JavaParserFacade.get(typeSolver).solve(node)) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.toString(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration>)
-  Line 149) JavaParserFacade.get(typeSolver).solve(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.MethodCallExpr)
-  Line 149) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 152) System.err.println("Error resolving call at L" + node.getBegin().get().line + ": " + node) ==> java.io.PrintStream.println(java.lang.String)
-  Line 152) node.getBegin().get() ==> java.util.Optional.get()
-  Line 152) node.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
-  Line 153) e.printStackTrace() ==> java.lang.Throwable.printStackTrace()
-  Line 160) methodDeclarationSymbolReference.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 161) methodDeclarationSymbolReference.getCorrespondingDeclaration().getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
-  Line 161) methodDeclarationSymbolReference.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 169) collectAllNodes(node, nodes) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.collectAllNodes(com.github.javaparser.ast.Node, java.util.List<com.github.javaparser.ast.Node>)
-  Line 170) nodes.sort((n1, n2) -> n1.getBegin().get().compareTo(n2.getBegin().get())) ==> java.util.List.sort(java.util.Comparator<? super E>)
-  Line 170) n1.getBegin().get().compareTo(n2.getBegin().get()) ==> ERROR
-  Line 170) n1.getBegin().get() ==> ERROR
-  Line 170) n1.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
-  Line 170) n2.getBegin().get() ==> ERROR
-  Line 170) n2.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
-  Line 175) nodes.add(node) ==> java.util.List.add(E)
-  Line 176) node.getChildNodes().forEach(c -> collectAllNodes(c, nodes)) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
-  Line 176) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 176) collectAllNodes(c, nodes) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.collectAllNodes(com.github.javaparser.ast.Node, java.util.List<com.github.javaparser.ast.Node>)
-  Line 180) file.isDirectory() ==> java.io.File.isDirectory()
-  Line 181) file.listFiles() ==> java.io.File.listFiles()
-  Line 182) solve(f) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solve(java.io.File)
-  Line 185) file.getName().endsWith(".java") ==> java.lang.String.endsWith(java.lang.String)
-  Line 185) file.getName() ==> java.io.File.getName()
-  Line 187) out.println("- parsing " + file.getAbsolutePath()) ==> java.io.PrintStream.println(java.lang.String)
-  Line 187) file.getAbsolutePath() ==> java.io.File.getAbsolutePath()
-  Line 189) JavaParser.parse(file) ==> com.github.javaparser.JavaParser.parse(java.io.File)
-  Line 190) collectAllNodes(cu) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.collectAllNodes(com.github.javaparser.ast.Node)
-  Line 191) nodes.forEach(n -> solve(n)) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
-  Line 191) solve(n) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solve(com.github.javaparser.ast.Node)
-  Line 197) file.isDirectory() ==> java.io.File.isDirectory()
-  Line 198) file.listFiles() ==> java.io.File.listFiles()
-  Line 199) solveMethodCalls(f) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveMethodCalls(java.io.File)
-  Line 202) file.getName().endsWith(".java") ==> java.lang.String.endsWith(java.lang.String)
-  Line 202) file.getName() ==> java.io.File.getName()
-  Line 204) out.println("- parsing " + file.getAbsolutePath()) ==> java.io.PrintStream.println(java.lang.String)
-  Line 204) file.getAbsolutePath() ==> java.io.File.getAbsolutePath()
-  Line 206) JavaParser.parse(file) ==> com.github.javaparser.JavaParser.parse(java.io.File)
-  Line 207) solveMethodCalls(cu) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveMethodCalls(com.github.javaparser.ast.Node)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparser_Navigator.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparser_Navigator.txt
deleted file mode 100644
index ea0f5e5..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparser_Navigator.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-  Line 44) node.getParentNode().orElse(null) ==> java.util.Optional.orElse(T)
-  Line 44) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
-  Line 49) cu.getTypes().isEmpty() ==> com.github.javaparser.ast.NodeList.isEmpty()
-  Line 49) cu.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
-  Line 50) Optional.empty() ==> java.util.Optional.empty()
-  Line 53) getOuterTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getOuterTypeName(java.lang.String)
-  Line 54) cu.getTypes().stream().filter((t) -> t.getName().getId().equals(typeName)).findFirst() ==> ERROR
-  Line 54) cu.getTypes().stream().filter((t) -> t.getName().getId().equals(typeName)) ==> ERROR
-  Line 54) cu.getTypes().stream() ==> java.util.Collection.stream()
-  Line 54) cu.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
-  Line 54) t.getName().getId().equals(typeName) ==> ERROR
-  Line 54) t.getName().getId() ==> ERROR
-  Line 54) t.getName() ==> ERROR
-  Line 56) getInnerTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getInnerTypeName(java.lang.String)
-  Line 57) type.isPresent() ==> java.util.Optional.isPresent()
-  Line 57) innerTypeName.isEmpty() ==> java.lang.String.isEmpty()
-  Line 58) findType(type.get(), innerTypeName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.body.TypeDeclaration<?>, java.lang.String)
-  Line 58) type.get() ==> java.util.Optional.get()
-  Line 64) getOuterTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getOuterTypeName(java.lang.String)
-  Line 66) Optional.empty() ==> java.util.Optional.empty()
-  Line 67) td.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 68) ((TypeDeclaration<?>) n).getName().getId().equals(typeName) ==> java.lang.String.equals(java.lang.Object)
-  Line 68) ((TypeDeclaration<?>) n).getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 68) ((TypeDeclaration<?>) n).getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 69) Optional.of((TypeDeclaration<?>) n) ==> java.util.Optional.of(T)
-  Line 73) getInnerTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getInnerTypeName(java.lang.String)
-  Line 74) type.isPresent() ==> java.util.Optional.isPresent()
-  Line 74) innerTypeName.isEmpty() ==> java.lang.String.isEmpty()
-  Line 75) findType(type.get(), innerTypeName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.body.TypeDeclaration<?>, java.lang.String)
-  Line 75) type.get() ==> java.util.Optional.get()
-  Line 81) demandClassOrInterface(cu, qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.demandClassOrInterface(com.github.javaparser.ast.CompilationUnit, java.lang.String)
-  Line 82) cd.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
-  Line 89) findType(cu, qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.CompilationUnit, java.lang.String)
-  Line 90) res.isPresent() ==> java.util.Optional.isPresent()
-  Line 93) res.get() ==> java.util.Optional.get()
-  Line 96) res.get() ==> java.util.Optional.get()
-  Line 101) cd.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 104) md.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 104) md.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 104) md.getName() ==> com.github.javaparser.ast.body.CallableDeclaration.getName()
-  Line 119) cd.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 122) fd.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
-  Line 123) vd.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 123) vd.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 123) vd.getName() ==> com.github.javaparser.ast.body.VariableDeclarator.getName()
-  Line 135) nameExpr.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
-  Line 135) nameExpr.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 135) nameExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 135) nameExpr.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
-  Line 139) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 140) findNameExpression(child, name) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNameExpression(com.github.javaparser.ast.Node, java.lang.String)
-  Line 151) nameExpr.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 151) nameExpr.getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 151) nameExpr.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 155) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 156) findSimpleName(child, name) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findSimpleName(com.github.javaparser.ast.Node, java.lang.String)
-  Line 167) methodCallExpr.getName().getId().equals(methodName) ==> java.lang.String.equals(java.lang.Object)
-  Line 167) methodCallExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 167) methodCallExpr.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
-  Line 171) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 172) findMethodCall(child, methodName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findMethodCall(com.github.javaparser.ast.Node, java.lang.String)
-  Line 183) variableDeclarator.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 183) variableDeclarator.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 183) variableDeclarator.getName() ==> com.github.javaparser.ast.body.VariableDeclarator.getName()
-  Line 187) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 188) demandVariableDeclaration(child, name) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.demandVariableDeclaration(com.github.javaparser.ast.Node, java.lang.String)
-  Line 197) findType(compilationUnit, qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.CompilationUnit, java.lang.String)
-  Line 198) res.isPresent() ==> java.util.Optional.isPresent()
-  Line 201) res.get() ==> java.util.Optional.get()
-  Line 202) res.get().getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 202) res.get().getClass() ==> java.lang.Object.getClass()
-  Line 202) res.get() ==> java.util.Optional.get()
-  Line 204) res.get() ==> java.util.Optional.get()
-  Line 209) findSwitchHelper(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findSwitchHelper(com.github.javaparser.ast.Node)
-  Line 218) findNodeOfGivenClassHelper(node, clazz) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNodeOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>)
-  Line 228) findAllNodesOfGivenClassHelper(node, clazz, res) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findAllNodesOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>, java.util.List<N>)
-  Line 233) findNodeOfGivenClass(method, ReturnStmt.class) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNodeOfGivenClass(com.github.javaparser.ast.Node, java.lang.Class<N>)
-  Line 237) node.getParentNode().isPresent() ==> java.util.Optional.isPresent()
-  Line 237) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
-  Line 238) Optional.empty() ==> java.util.Optional.empty()
-  Line 239) clazz.isInstance(node.getParentNode().get()) ==> java.lang.Class.isInstance(java.lang.Object)
-  Line 239) node.getParentNode().get() ==> java.util.Optional.get()
-  Line 239) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
-  Line 240) Optional.of(clazz.cast(node.getParentNode().get())) ==> java.util.Optional.of(T)
-  Line 240) clazz.cast(node.getParentNode().get()) ==> java.lang.Class.cast(java.lang.Object)
-  Line 240) node.getParentNode().get() ==> java.util.Optional.get()
-  Line 240) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
-  Line 242) findAncestor(node.getParentNode().get(), clazz) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findAncestor(com.github.javaparser.ast.Node, java.lang.Class<N>)
-  Line 242) node.getParentNode().get() ==> java.util.Optional.get()
-  Line 242) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
-  Line 251) qualifiedName.split("\\.", 2) ==> java.lang.String.split(java.lang.String, int)
-  Line 255) qualifiedName.contains(".") ==> java.lang.String.contains(java.lang.CharSequence)
-  Line 256) qualifiedName.split("\\.", 2) ==> java.lang.String.split(java.lang.String, int)
-  Line 265) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 266) findSwitchHelper(child) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findSwitchHelper(com.github.javaparser.ast.Node)
-  Line 275) clazz.isInstance(node) ==> java.lang.Class.isInstance(java.lang.Object)
-  Line 276) clazz.cast(node) ==> java.lang.Class.cast(java.lang.Object)
-  Line 278) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 279) findNodeOfGivenClassHelper(child, clazz) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNodeOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>)
-  Line 288) clazz.isInstance(node) ==> java.lang.Class.isInstance(java.lang.Object)
-  Line 289) collector.add(clazz.cast(node)) ==> java.util.List.add(E)
-  Line 289) clazz.cast(node) ==> java.lang.Class.cast(java.lang.Object)
-  Line 291) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
-  Line 292) findAllNodesOfGivenClassHelper(child, clazz, collector) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findAllNodesOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>, java.util.List<N>)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt
deleted file mode 100644
index bb9ceb3..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt
+++ /dev/null
@@ -1,253 +0,0 @@
-  Line 58) Logger.getLogger(JavaParserFacade.class.getCanonicalName()) ==> java.util.logging.Logger.getLogger(java.lang.String)
-  Line 58) JavaParserFacade.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 61) logger.setLevel(Level.INFO) ==> java.util.logging.Logger.setLevel(java.util.logging.Level)
-  Line 63) consoleHandler.setLevel(Level.INFO) ==> java.util.logging.Handler.setLevel(java.util.logging.Level)
-  Line 64) logger.addHandler(consoleHandler) ==> java.util.logging.Logger.addHandler(java.util.logging.Handler)
-  Line 75) typeSolver.getRoot() ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.getRoot()
-  Line 89) instances.computeIfAbsent(typeSolver, JavaParserFacade::new) ==> java.util.Map.computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>)
-  Line 96) instances.clear() ==> java.util.Map.clear()
-  Line 100) type.isTypeVariable() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isTypeVariable()
-  Line 101) context.solveGenericType(type.describe(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveGenericType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 101) type.describe() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.describe()
-  Line 102) solved.isPresent() ==> java.util.Optional.isPresent()
-  Line 103) solved.get() ==> java.util.Optional.get()
-  Line 107) type.isWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isWildcard()
-  Line 108) type.asWildcard().isExtends() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.isExtends()
-  Line 108) type.asWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asWildcard()
-  Line 108) type.asWildcard().isSuper() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.isSuper()
-  Line 108) type.asWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asWildcard()
-  Line 109) type.asWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asWildcard()
-  Line 110) solveGenericTypes(wildcardUsage.getBoundedType(), context, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveGenericTypes(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.core.resolution.Context, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 110) wildcardUsage.getBoundedType() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.getBoundedType()
-  Line 111) wildcardUsage.isExtends() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.isExtends()
-  Line 112) Wildcard.extendsBound(boundResolved) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.extendsBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 114) Wildcard.superBound(boundResolved) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.superBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 126) symbolSolver.solveSymbol(nameExpr.getName().getId(), nameExpr) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbol(java.lang.String, com.github.javaparser.ast.Node)
-  Line 126) nameExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 126) nameExpr.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
-  Line 130) symbolSolver.solveSymbol(nameExpr.getId(), nameExpr) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbol(java.lang.String, com.github.javaparser.ast.Node)
-  Line 130) nameExpr.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 135) solve((NameExpr) expr) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.NameExpr)
-  Line 137) expr.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 137) expr.getClass() ==> java.lang.Object.getClass()
-  Line 142) solve(methodCallExpr, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.MethodCallExpr, boolean)
-  Line 146) solve(objectCreationExpr, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.ObjectCreationExpr, boolean)
-  Line 150) solve(explicitConstructorInvocationStmt, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt, boolean)
-  Line 157) solveArguments(explicitConstructorInvocationStmt, explicitConstructorInvocationStmt.getArguments(), solveLambdas, argumentTypes, placeholders) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveArguments(com.github.javaparser.ast.Node, com.github.javaparser.ast.NodeList<com.github.javaparser.ast.expr.Expression>, boolean, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, java.util.List<com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder>)
-  Line 157) explicitConstructorInvocationStmt.getArguments() ==> com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt.getArguments()
-  Line 159) explicitConstructorInvocationStmt.getAncestorOfType(ClassOrInterfaceDeclaration.class) ==> com.github.javaparser.HasParentNode.getAncestorOfType(java.lang.Class<N>)
-  Line 160) optAncestor.isPresent() ==> java.util.Optional.isPresent()
-  Line 161) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 163) optAncestor.get() ==> java.util.Optional.get()
-  Line 165) explicitConstructorInvocationStmt.isThis() ==> com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt.isThis()
-  Line 166) JavaParserFacade.get(typeSolver).convert(classNode.getExtendedTypes(0), classNode) ==> UNSOLVED
-  Line 166) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 166) classNode.getExtendedTypes(0) ==> com.github.javaparser.ast.nodeTypes.NodeWithExtends.getExtendedTypes(int)
-  Line 167) classDecl.isReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isReferenceType()
-  Line 168) classDecl.asReferenceType().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 168) classDecl.asReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asReferenceType()
-  Line 171) JavaParserFactory.getContext(classNode, typeSolver).solveType(classNode.getNameAsString(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 171) JavaParserFactory.getContext(classNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 171) classNode.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithSimpleName.getNameAsString()
-  Line 172) sr.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 173) sr.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 177) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 179) ConstructorResolutionLogic.findMostApplicable(((ClassDeclaration) typeDecl).getConstructors(), argumentTypes, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic.findMostApplicable(java.util.List<com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration>, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 179) ((ClassDeclaration) typeDecl).getConstructors() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getConstructors()
-  Line 181) placeholder.setMethod(res) ==> com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder.setMethod(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration>)
-  Line 188) node.getClassExpr().isPresent() ==> java.util.Optional.isPresent()
-  Line 188) node.getClassExpr() ==> com.github.javaparser.ast.expr.ThisExpr.getClassExpr()
-  Line 190) node.getClassExpr().get().toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 190) node.getClassExpr().get() ==> java.util.Optional.get()
-  Line 190) node.getClassExpr() ==> com.github.javaparser.ast.expr.ThisExpr.getClassExpr()
-  Line 192) typeSolver.tryToSolveType(className) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 193) clazz.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 194) SymbolReference.solved(clazz.getCorrespondingDeclaration()) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 194) clazz.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 197) node.getAncestorOfType(CompilationUnit.class) ==> com.github.javaparser.HasParentNode.getAncestorOfType(java.lang.Class<N>)
-  Line 198) cu.isPresent() ==> java.util.Optional.isPresent()
-  Line 199) cu.get().getClassByName(className) ==> com.github.javaparser.ast.CompilationUnit.getClassByName(java.lang.String)
-  Line 199) cu.get() ==> java.util.Optional.get()
-  Line 200) classByName.isPresent() ==> java.util.Optional.isPresent()
-  Line 201) SymbolReference.solved(getTypeDeclaration(classByName.get())) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 201) getTypeDeclaration(classByName.get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 201) classByName.get() ==> java.util.Optional.get()
-  Line 205) SymbolReference.solved(getTypeDeclaration(findContainingTypeDecl(node))) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 205) getTypeDeclaration(findContainingTypeDecl(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 205) findContainingTypeDecl(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.findContainingTypeDecl(com.github.javaparser.ast.Node)
-  Line 215) solveArguments(objectCreationExpr, objectCreationExpr.getArguments(), solveLambdas, argumentTypes, placeholders) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveArguments(com.github.javaparser.ast.Node, com.github.javaparser.ast.NodeList<com.github.javaparser.ast.expr.Expression>, boolean, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, java.util.List<com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder>)
-  Line 215) objectCreationExpr.getArguments() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getArguments()
-  Line 217) JavaParserFacade.get(typeSolver).convert(objectCreationExpr.getType(), objectCreationExpr) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
-  Line 217) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 217) objectCreationExpr.getType() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getType()
-  Line 218) classDecl.isReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isReferenceType()
-  Line 219) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 221) ConstructorResolutionLogic.findMostApplicable(((ClassDeclaration) classDecl.asReferenceType().getTypeDeclaration()).getConstructors(), argumentTypes, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic.findMostApplicable(java.util.List<com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration>, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 221) ((ClassDeclaration) classDecl.asReferenceType().getTypeDeclaration()).getConstructors() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getConstructors()
-  Line 221) classDecl.asReferenceType().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 221) classDecl.asReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asReferenceType()
-  Line 223) placeholder.setMethod(res) ==> com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder.setMethod(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration>)
-  Line 233) argumentTypes.add(placeholder) ==> java.util.List.add(E)
-  Line 234) placeholders.add(placeholder) ==> java.util.List.add(E)
-  Line 237) argumentTypes.add(JavaParserFacade.get(typeSolver).getType(parameterValue, solveLambdas)) ==> java.util.List.add(E)
-  Line 237) JavaParserFacade.get(typeSolver).getType(parameterValue, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
-  Line 237) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 241) String.format("Unable to calculate the type of a parameter of a method call. Method call: %s, Parameter: %s", node, parameterValue) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
-  Line 256) solveArguments(methodCallExpr, methodCallExpr.getArguments(), solveLambdas, argumentTypes, placeholders) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveArguments(com.github.javaparser.ast.Node, com.github.javaparser.ast.NodeList<com.github.javaparser.ast.expr.Expression>, boolean, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, java.util.List<com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder>)
-  Line 256) methodCallExpr.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
-  Line 258) JavaParserFactory.getContext(methodCallExpr, typeSolver).solveMethod(methodCallExpr.getName().getId(), argumentTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 258) JavaParserFactory.getContext(methodCallExpr, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 258) methodCallExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 258) methodCallExpr.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
-  Line 260) placeholder.setMethod(res) ==> com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder.setMethod(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration>)
-  Line 266) JavaParserFactory.getContext(annotationExpr, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 267) context.solveType(annotationExpr.getNameAsString(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 267) annotationExpr.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
-  Line 268) typeDeclarationSymbolReference.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 269) typeDeclarationSymbolReference.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 270) SymbolReference.solved(annotationDeclaration) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 272) SymbolReference.unsolved(AnnotationDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 277) getType(node, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
-  Line 282) cacheWithLambdasSolved.containsKey(node) ==> java.util.Map.containsKey(java.lang.Object)
-  Line 283) getTypeConcrete(node, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
-  Line 285) cacheWithLambdasSolved.put(node, res) ==> java.util.Map.put(K, V)
-  Line 290) methodCallExpr.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
-  Line 291) cacheWithLambdasSolved.containsKey(arg) ==> java.util.Map.containsKey(java.lang.Object)
-  Line 292) getType(arg, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
-  Line 298) cacheWithLambdasSolved.remove(node) ==> java.util.Map.remove(java.lang.Object)
-  Line 299) cacheWithLambdasSolved.put(node, getType(node, true)) ==> java.util.Map.put(K, V)
-  Line 299) getType(node, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
-  Line 301) logger.finer("getType on " + node + " -> " + res) ==> java.util.logging.Logger.finer(java.lang.String)
-  Line 303) cacheWithLambdasSolved.get(node) ==> java.util.Map.get(java.lang.Object)
-  Line 305) find(cacheWithLambdasSolved, node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.find(java.util.Map<com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.ast.Node)
-  Line 306) res.isPresent() ==> java.util.Optional.isPresent()
-  Line 307) res.get() ==> java.util.Optional.get()
-  Line 309) find(cacheWithoutLambdasSolved, node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.find(java.util.Map<com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.ast.Node)
-  Line 310) res.isPresent() ==> java.util.Optional.isPresent()
-  Line 311) getTypeConcrete(node, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
-  Line 312) cacheWithoutLambdasSolved.put(node, resType) ==> java.util.Map.put(K, V)
-  Line 313) logger.finer("getType on " + node + " (no solveLambdas) -> " + res) ==> java.util.logging.Logger.finer(java.lang.String)
-  Line 316) res.get() ==> java.util.Optional.get()
-  Line 321) map.containsKey(node) ==> java.util.Map.containsKey(java.lang.Object)
-  Line 322) Optional.of(map.get(node)) ==> java.util.Optional.of(T)
-  Line 322) map.get(node) ==> java.util.Map.get(java.lang.Object)
-  Line 325) find(map, (LambdaExpr) node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.find(java.util.Map<com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.ast.expr.LambdaExpr)
-  Line 327) Optional.empty() ==> java.util.Optional.empty()
-  Line 338) map.keySet() ==> java.util.Map.keySet()
-  Line 341) keyLambdaExpr.toString().equals(lambdaExpr.toString()) ==> java.lang.String.equals(java.lang.Object)
-  Line 341) keyLambdaExpr.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 341) lambdaExpr.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 341) getParentNode(keyLambdaExpr) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 341) getParentNode(lambdaExpr) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 342) Optional.of(map.get(keyLambdaExpr)) ==> java.util.Optional.of(T)
-  Line 342) map.get(keyLambdaExpr) ==> java.util.Map.get(java.lang.Object)
-  Line 346) Optional.empty() ==> java.util.Optional.empty()
-  Line 350) methodReferenceExpr.getScope() ==> com.github.javaparser.ast.expr.MethodReferenceExpr.getScope()
-  Line 353) methodReferenceExpr.getScope() ==> com.github.javaparser.ast.expr.MethodReferenceExpr.getScope()
-  Line 354) typeExpr.getType() ==> com.github.javaparser.ast.expr.TypeExpr.getType()
-  Line 355) typeExpr.getType().getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 355) typeExpr.getType().getClass() ==> java.lang.Object.getClass()
-  Line 355) typeExpr.getType() ==> com.github.javaparser.ast.expr.TypeExpr.getType()
-  Line 357) typeExpr.getType() ==> com.github.javaparser.ast.expr.TypeExpr.getType()
-  Line 358) JavaParserFactory.getContext(classOrInterfaceType, typeSolver).solveType(classOrInterfaceType.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 358) JavaParserFactory.getContext(classOrInterfaceType, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 358) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 358) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 359) typeDeclarationSymbolReference.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream().filter(it -> it.getName().equals(methodReferenceExpr.getIdentifier())).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
-  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream().filter(it -> it.getName().equals(methodReferenceExpr.getIdentifier())) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
-  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream() ==> java.util.Collection.stream()
-  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllMethods()
-  Line 362) typeDeclarationSymbolReference.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 362) it.getName().equals(methodReferenceExpr.getIdentifier()) ==> java.lang.String.equals(java.lang.Object)
-  Line 362) it.getName() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.getName()
-  Line 362) methodReferenceExpr.getIdentifier() ==> com.github.javaparser.ast.expr.MethodReferenceExpr.getIdentifier()
-  Line 362) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 363) methodUsages.size() ==> java.util.List.size()
-  Line 367) methodUsages.get(0) ==> java.util.List.get(int)
-  Line 374) getTypeConcrete(left, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
-  Line 375) getTypeConcrete(right, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
-  Line 376) rightType.isAssignableBy(leftType) ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 391) node.accept(typeExtractor, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 399) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 402) findContainingTypeDecl(getParentNode(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.findContainingTypeDecl(com.github.javaparser.ast.Node)
-  Line 402) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 407) JavaParserFacade.get(typeSolver).convertToUsage(var.getType(), var) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
-  Line 407) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 407) var.getType() ==> com.github.javaparser.ast.body.VariableDeclarator.getType()
-  Line 415) convertToUsage(type, JavaParserFactory.getContext(context, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 415) JavaParserFactory.getContext(context, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 419) convertToUsage(type, type) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
-  Line 424) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 424) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 425) classOrInterfaceType.getScope().isPresent() ==> java.util.Optional.isPresent()
-  Line 425) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 426) qName(classOrInterfaceType.getScope().get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.qName(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 426) classOrInterfaceType.getScope().get() ==> java.util.Optional.get()
-  Line 426) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 435) qName(classOrInterfaceType) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.qName(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 436) context.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 437) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 440) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 441) Collections.emptyList() ==> java.util.Collections.emptyList()
-  Line 442) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
-  Line 442) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 443) classOrInterfaceType.getTypeArguments().get().stream().map((pt) -> convertToUsage(pt, context)).collect(Collectors.toList()) ==> ERROR
-  Line 443) classOrInterfaceType.getTypeArguments().get().stream().map((pt) -> convertToUsage(pt, context)) ==> ERROR
-  Line 443) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
-  Line 443) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
-  Line 443) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 443) convertToUsage(pt, context) ==> ERROR
-  Line 443) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 445) typeDeclaration.isTypeParameter() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isTypeParameter()
-  Line 450) javaParserTypeVariableDeclaration.asTypeParameter() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration.asTypeParameter()
-  Line 456) PrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) type).getType().name()) ==> com.github.javaparser.symbolsolver.model.typesystem.PrimitiveType.byName(java.lang.String)
-  Line 456) ((com.github.javaparser.ast.type.PrimitiveType) type).getType().name() ==> java.lang.Enum.name()
-  Line 456) ((com.github.javaparser.ast.type.PrimitiveType) type).getType() ==> com.github.javaparser.ast.type.PrimitiveType.getType()
-  Line 459) wildcardType.getExtendedTypes().isPresent() ==> java.util.Optional.isPresent()
-  Line 459) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
-  Line 459) wildcardType.getSuperTypes().isPresent() ==> java.util.Optional.isPresent()
-  Line 459) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
-  Line 460) Wildcard.extendsBound(convertToUsage(wildcardType.getExtendedTypes().get(), context)) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.extendsBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 460) convertToUsage(wildcardType.getExtendedTypes().get(), context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 460) wildcardType.getExtendedTypes().get() ==> java.util.Optional.get()
-  Line 460) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
-  Line 461) wildcardType.getExtendedTypes().isPresent() ==> java.util.Optional.isPresent()
-  Line 461) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
-  Line 461) wildcardType.getSuperTypes().isPresent() ==> java.util.Optional.isPresent()
-  Line 461) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
-  Line 462) Wildcard.superBound(convertToUsage(wildcardType.getSuperTypes().get(), context)) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.superBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 462) convertToUsage(wildcardType.getSuperTypes().get(), context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 462) wildcardType.getSuperTypes().get() ==> java.util.Optional.get()
-  Line 462) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
-  Line 463) wildcardType.getExtendedTypes().isPresent() ==> java.util.Optional.isPresent()
-  Line 463) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
-  Line 463) wildcardType.getSuperTypes().isPresent() ==> java.util.Optional.isPresent()
-  Line 463) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
-  Line 466) wildcardType.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 472) convertToUsage(jpArrayType.getComponentType(), context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 472) jpArrayType.getComponentType() ==> com.github.javaparser.ast.type.ArrayType.getComponentType()
-  Line 474) type.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 474) type.getClass() ==> java.lang.Object.getClass()
-  Line 480) convert(type, JavaParserFactory.getContext(node, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 480) JavaParserFactory.getContext(node, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 484) convertToUsage(type, context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 489) call.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
-  Line 490) call.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
-  Line 493) params.add(getType(param, false)) ==> java.util.List.add(E)
-  Line 493) getType(param, false) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
-  Line 495) String.format("Error calculating the type of parameter %s of method call %s", param, call) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
-  Line 500) JavaParserFactory.getContext(call, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 501) context.solveMethodAsUsage(call.getName().getId(), params, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethodAsUsage(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 501) call.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 501) call.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
-  Line 502) methodUsage.isPresent() ==> java.util.Optional.isPresent()
-  Line 503) call.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
-  Line 504) call.getRange().get() ==> java.util.Optional.get()
-  Line 504) call.getRange() ==> com.github.javaparser.ast.Node.getRange()
-  Line 506) methodUsage.get() ==> java.util.Optional.get()
-  Line 510) JavaParserFactory.toTypeDeclaration(classOrInterfaceDeclaration, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.toTypeDeclaration(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 519) getTypeDeclaration((ClassOrInterfaceDeclaration) node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 524) getTypeOfThisIn(getParentNode(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeOfThisIn(com.github.javaparser.ast.Node)
-  Line 524) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 529) JavaParserFactory.toTypeDeclaration(typeDeclaration, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.toTypeDeclaration(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor_J9.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor_J9.txt
deleted file mode 100644
index 28c113f..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor_J9.txt
+++ /dev/null
@@ -1,279 +0,0 @@
-  Line 41) Logger.getLogger(TypeExtractor.class.getCanonicalName()) ==> java.util.logging.Logger.getLogger(java.lang.String)
-  Line 41) TypeExtractor.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 44) logger.setLevel(Level.INFO) ==> java.util.logging.Logger.setLevel(java.util.logging.Level)
-  Line 46) consoleHandler.setLevel(Level.INFO) ==> java.util.logging.Handler.setLevel(java.util.logging.Level)
-  Line 47) logger.addHandler(consoleHandler) ==> java.util.logging.Logger.addHandler(java.util.logging.Handler)
-  Line 60) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 62) facade.convertToUsageVariableType(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsageVariableType(com.github.javaparser.ast.body.VariableDeclarator)
-  Line 63) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 65) facade.convertToUsageVariableType(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsageVariableType(com.github.javaparser.ast.body.VariableDeclarator)
-  Line 67) getParentNode(node).getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 67) getParentNode(node).getClass() ==> java.lang.Object.getClass()
-  Line 67) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 73) node.getType() ==> com.github.javaparser.ast.body.Parameter.getType()
-  Line 76) facade.convertToUsage(node.getType(), node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
-  Line 76) node.getType() ==> com.github.javaparser.ast.body.Parameter.getType()
-  Line 82) node.getName().accept(this, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 82) node.getName() ==> com.github.javaparser.ast.expr.ArrayAccessExpr.getName()
-  Line 83) arrayUsageType.isArray() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isArray()
-  Line 84) ((ArrayType) arrayUsageType).getComponentType() ==> com.github.javaparser.symbolsolver.model.typesystem.ArrayType.getComponentType()
-  Line 91) facade.convertToUsage(node.getElementType(), JavaParserFactory.getContext(node, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 91) node.getElementType() ==> com.github.javaparser.ast.expr.ArrayCreationExpr.getElementType()
-  Line 91) JavaParserFactory.getContext(node, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 92) node.getLevels().size() ==> com.github.javaparser.ast.NodeList.size()
-  Line 92) node.getLevels() ==> com.github.javaparser.ast.expr.ArrayCreationExpr.getLevels()
-  Line 100) node.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 100) node.getClass() ==> java.lang.Object.getClass()
-  Line 105) node.getTarget().accept(this, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 105) node.getTarget() ==> com.github.javaparser.ast.expr.AssignExpr.getTarget()
-  Line 110) node.getOperator() ==> com.github.javaparser.ast.expr.BinaryExpr.getOperator()
-  Line 115) facade.getBinaryTypeConcrete(node.getLeft(), node.getRight(), solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getBinaryTypeConcrete(com.github.javaparser.ast.Node, com.github.javaparser.ast.Node, boolean)
-  Line 115) node.getLeft() ==> com.github.javaparser.ast.expr.BinaryExpr.getLeft()
-  Line 115) node.getRight() ==> com.github.javaparser.ast.expr.BinaryExpr.getRight()
-  Line 132) node.getLeft().accept(this, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 132) node.getLeft() ==> com.github.javaparser.ast.expr.BinaryExpr.getLeft()
-  Line 134) node.getOperator().name() ==> java.lang.Enum.name()
-  Line 134) node.getOperator() ==> com.github.javaparser.ast.expr.BinaryExpr.getOperator()
-  Line 140) facade.convertToUsage(node.getType(), JavaParserFactory.getContext(node, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 140) node.getType() ==> com.github.javaparser.ast.expr.CastExpr.getType()
-  Line 140) JavaParserFactory.getContext(node, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 146) node.getType() ==> com.github.javaparser.ast.expr.ClassExpr.getType()
-  Line 147) facade.convertToUsage(astType, node.getType()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
-  Line 147) node.getType() ==> com.github.javaparser.ast.expr.ClassExpr.getType()
-  Line 148) ImmutableList.of(jssType) ==> java.util.List.of(E...)
-  Line 153) node.getThenExpr().accept(this, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 153) node.getThenExpr() ==> com.github.javaparser.ast.expr.ConditionalExpr.getThenExpr()
-  Line 158) node.getInner().accept(this, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 158) node.getInner() ==> com.github.javaparser.ast.expr.EnclosedExpr.getInner()
-  Line 168) parentType.hasField(node.getName().getId()) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.hasField(java.lang.String)
-  Line 168) node.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 168) node.getName() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getName()
-  Line 169) parentType.getField(node.getName().getId()).getType() ==> com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration.getType()
-  Line 169) parentType.getField(node.getName().getId()) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getField(java.lang.String)
-  Line 169) node.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 169) node.getName() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getName()
-  Line 170) parentType.hasInternalType(node.getName().getId()) ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.hasInternalType(java.lang.String)
-  Line 170) node.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 170) node.getName() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getName()
-  Line 171) parentType.getInternalType(node.getName().getId()) ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getInternalType(java.lang.String)
-  Line 171) node.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 171) node.getName() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getName()
-  Line 173) node.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 173) node.getName() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getName()
-  Line 180) node.getScope() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getScope()
-  Line 181) node.getScope() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getScope()
-  Line 182) node.getScope() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getScope()
-  Line 183) JavaParserFactory.getContext(node, typeSolver).solveType(staticValue.toString(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 183) JavaParserFactory.getContext(node, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 183) staticValue.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 184) typeAccessedStatically.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 186) solveDotExpressionType(typeAccessedStatically.getCorrespondingDeclaration().asReferenceType(), node) ==> com.github.javaparser.symbolsolver.javaparsermodel.TypeExtractor.solveDotExpressionType(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration, com.github.javaparser.ast.expr.FieldAccessExpr)
-  Line 187) typeAccessedStatically.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 187) typeAccessedStatically.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 189) node.getScope() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getScope()
-  Line 192) facade.solve((ThisExpr) node.getScope()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.ThisExpr)
-  Line 192) node.getScope() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getScope()
-  Line 194) solve.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 195) solve.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 197) solveDotExpressionType(correspondingDeclaration.asReferenceType(), node) ==> com.github.javaparser.symbolsolver.javaparsermodel.TypeExtractor.solveDotExpressionType(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration, com.github.javaparser.ast.expr.FieldAccessExpr)
-  Line 197) correspondingDeclaration.asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 201) node.getScope().toString().indexOf('.') ==> java.lang.String.indexOf(int)
-  Line 201) node.getScope().toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 201) node.getScope() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getScope()
-  Line 203) typeSolver.tryToSolveType(node.getScope().toString()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 203) node.getScope().toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 203) node.getScope() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getScope()
-  Line 204) sr.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 205) solveDotExpressionType(sr.getCorrespondingDeclaration(), node) ==> com.github.javaparser.symbolsolver.javaparsermodel.TypeExtractor.solveDotExpressionType(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration, com.github.javaparser.ast.expr.FieldAccessExpr)
-  Line 205) sr.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 210) new SymbolSolver(typeSolver).solveSymbolAsValue(node.getField().getId(), node) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolAsValue(java.lang.String, com.github.javaparser.ast.Node)
-  Line 210) node.getField().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 210) node.getField() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getField()
-  Line 214) typeSolver.tryToSolveType(node.toString()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 214) node.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 215) sref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 216) sref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 219) value.isPresent() ==> java.util.Optional.isPresent()
-  Line 220) value.get().getType() ==> com.github.javaparser.symbolsolver.model.resolution.Value.getType()
-  Line 220) value.get() ==> java.util.Optional.get()
-  Line 222) node.getField().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 222) node.getField() ==> com.github.javaparser.ast.expr.FieldAccessExpr.getField()
-  Line 233) new ReflectionTypeSolver().solveType("java.lang.String") ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 253) node.getValue().toLowerCase().endsWith("f") ==> java.lang.String.endsWith(java.lang.String)
-  Line 253) node.getValue().toLowerCase() ==> java.lang.String.toLowerCase()
-  Line 253) node.getValue() ==> com.github.javaparser.ast.expr.LiteralStringValueExpr.getValue()
-  Line 271) logger.finest("getType on method call " + node) ==> java.util.logging.Logger.finest(java.lang.String)
-  Line 273) facade.solveMethodAsUsage(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveMethodAsUsage(com.github.javaparser.ast.expr.MethodCallExpr)
-  Line 274) logger.finest("getType on method call " + node + " resolved to " + ref) ==> java.util.logging.Logger.finest(java.lang.String)
-  Line 275) logger.finest("getType on method call " + node + " return type is " + ref.returnType()) ==> java.util.logging.Logger.finest(java.lang.String)
-  Line 275) ref.returnType() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.returnType()
-  Line 276) ref.returnType() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.returnType()
-  Line 282) logger.finest("getType on name expr " + node) ==> java.util.logging.Logger.finest(java.lang.String)
-  Line 283) new SymbolSolver(typeSolver).solveSymbolAsValue(node.getName().getId(), node) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolAsValue(java.lang.String, com.github.javaparser.ast.Node)
-  Line 283) node.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 283) node.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
-  Line 284) value.isPresent() ==> java.util.Optional.isPresent()
-  Line 285) node.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 285) node.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
-  Line 287) value.get().getType() ==> com.github.javaparser.symbolsolver.model.resolution.Value.getType()
-  Line 287) value.get() ==> java.util.Optional.get()
-  Line 293) facade.convertToUsage(node.getType(), node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
-  Line 293) node.getType() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getType()
-  Line 300) node.getClassExpr().isPresent() ==> java.util.Optional.isPresent()
-  Line 300) node.getClassExpr() ==> com.github.javaparser.ast.expr.ThisExpr.getClassExpr()
-  Line 302) node.getClassExpr().get().toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 302) node.getClassExpr().get() ==> java.util.Optional.get()
-  Line 302) node.getClassExpr() ==> com.github.javaparser.ast.expr.ThisExpr.getClassExpr()
-  Line 304) typeSolver.tryToSolveType(className) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 305) clazz.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 306) clazz.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 309) node.getAncestorOfType(CompilationUnit.class) ==> com.github.javaparser.HasParentNode.getAncestorOfType(java.lang.Class<N>)
-  Line 310) cu.isPresent() ==> java.util.Optional.isPresent()
-  Line 311) cu.get().getClassByName(className) ==> com.github.javaparser.ast.CompilationUnit.getClassByName(java.lang.String)
-  Line 311) cu.get() ==> java.util.Optional.get()
-  Line 312) classByName.isPresent() ==> java.util.Optional.isPresent()
-  Line 313) facade.getTypeDeclaration(classByName.get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 313) classByName.get() ==> java.util.Optional.get()
-  Line 318) facade.getTypeDeclaration(facade.findContainingTypeDecl(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 318) facade.findContainingTypeDecl(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.findContainingTypeDecl(com.github.javaparser.ast.Node)
-  Line 323) facade.getTypeDeclaration(facade.findContainingTypeDecl(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 323) facade.findContainingTypeDecl(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.findContainingTypeDecl(com.github.javaparser.ast.Node)
-  Line 325) ((ClassDeclaration) typeOfNode).getSuperClass() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getSuperClass()
-  Line 327) node.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 327) node.getClass() ==> java.lang.Object.getClass()
-  Line 333) node.getOperator() ==> com.github.javaparser.ast.expr.UnaryExpr.getOperator()
-  Line 336) node.getExpression().accept(this, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 336) node.getExpression() ==> com.github.javaparser.ast.expr.UnaryExpr.getExpression()
-  Line 343) node.getExpression().accept(this, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
-  Line 343) node.getExpression() ==> com.github.javaparser.ast.expr.UnaryExpr.getExpression()
-  Line 345) node.getOperator().name() ==> java.lang.Enum.name()
-  Line 345) node.getOperator() ==> com.github.javaparser.ast.expr.UnaryExpr.getOperator()
-  Line 351) node.getVariables().size() ==> com.github.javaparser.ast.NodeList.size()
-  Line 351) node.getVariables() ==> com.github.javaparser.ast.expr.VariableDeclarationExpr.getVariables()
-  Line 354) facade.convertToUsageVariableType(node.getVariables().get(0)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsageVariableType(com.github.javaparser.ast.body.VariableDeclarator)
-  Line 354) node.getVariables().get(0) ==> com.github.javaparser.ast.NodeList.get(int)
-  Line 354) node.getVariables() ==> com.github.javaparser.ast.expr.VariableDeclarationExpr.getVariables()
-  Line 360) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 361) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 362) JavaParserSymbolDeclaration.getParamPos(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration.getParamPos(com.github.javaparser.ast.Node)
-  Line 363) facade.solve(callExpr) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.MethodCallExpr)
-  Line 364) refMethod.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 365) getParentNode(node).toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 365) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 365) callExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 365) callExpr.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
-  Line 367) logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName()) ==> java.util.logging.Logger.finest(java.lang.String)
-  Line 367) refMethod.getCorrespondingDeclaration().getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
-  Line 367) refMethod.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 371) refMethod.getCorrespondingDeclaration().getParam(pos).getType() ==> com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration.getType()
-  Line 371) refMethod.getCorrespondingDeclaration().getParam(pos) ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getParam(int)
-  Line 371) refMethod.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 373) callExpr.getScope().isPresent() ==> java.util.Optional.isPresent()
-  Line 373) callExpr.getScope() ==> com.github.javaparser.ast.expr.MethodCallExpr.getScope()
-  Line 374) callExpr.getScope().get() ==> java.util.Optional.get()
-  Line 374) callExpr.getScope() ==> com.github.javaparser.ast.expr.MethodCallExpr.getScope()
-  Line 381) JavaParserFactory.getContext(nameExpr, typeSolver).solveType(nameExpr.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 381) JavaParserFactory.getContext(nameExpr, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 381) nameExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 381) nameExpr.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
-  Line 382) type.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 391) facade.getType(scope) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node)
-  Line 392) scopeType.isReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isReferenceType()
-  Line 393) scopeType.asReferenceType().useThisTypeParametersOnTheGivenType(result) ==> com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParameterValueProvider.useThisTypeParametersOnTheGivenType(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 393) scopeType.asReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asReferenceType()
-  Line 399) JavaParserFactory.getContext(node, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 400) facade.solveGenericTypes(result, ctx, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveGenericTypes(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.core.resolution.Context, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 405) FunctionalInterfaceLogic.getFunctionalMethod(result) ==> com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic.getFunctionalMethod(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 406) functionalMethod.isPresent() ==> java.util.Optional.isPresent()
-  Line 415) ReferenceTypeImpl.undeterminedParameters(functionalMethod.get().getDeclaration().declaringType(), typeSolver) ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl.undeterminedParameters(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 415) functionalMethod.get().getDeclaration().declaringType() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.declaringType()
-  Line 415) functionalMethod.get().getDeclaration() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.getDeclaration()
-  Line 415) functionalMethod.get() ==> java.util.Optional.get()
-  Line 417) lambdaCtx.addPair(result, functionalInterfaceType) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.addPair(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 421) lambdaExpr.getBody() ==> com.github.javaparser.ast.expr.LambdaExpr.getBody()
-  Line 422) facade.getType(((ExpressionStmt) lambdaExpr.getBody()).getExpression()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node)
-  Line 422) ((ExpressionStmt) lambdaExpr.getBody()).getExpression() ==> com.github.javaparser.ast.stmt.ExpressionStmt.getExpression()
-  Line 422) lambdaExpr.getBody() ==> com.github.javaparser.ast.expr.LambdaExpr.getBody()
-  Line 423) lambdaExpr.getBody() ==> com.github.javaparser.ast.expr.LambdaExpr.getBody()
-  Line 424) lambdaExpr.getBody() ==> com.github.javaparser.ast.expr.LambdaExpr.getBody()
-  Line 425) blockStmt.getStatements() ==> com.github.javaparser.ast.stmt.BlockStmt.getStatements()
-  Line 428) blockStmt.getNodesByType(ReturnStmt.class) ==> com.github.javaparser.ast.Node.getNodesByType(java.lang.Class<N>)
-  Line 430) returnStmts.size() ==> java.util.List.size()
-  Line 432) returnStmts.stream().map(returnStmt -> {
-    Optional<Expression> expression = returnStmt.getExpression();
-    if (expression.isPresent()) {
-        return facade.getType(expression.get());
-    } else {
-        return VoidType.INSTANCE;
-    }
-}).filter(x -> x != null && !x.isVoid() && !x.isNull()).findFirst().orElse(VoidType.INSTANCE) ==> java.util.Optional.orElse(T)
-  Line 432) returnStmts.stream().map(returnStmt -> {
-    Optional<Expression> expression = returnStmt.getExpression();
-    if (expression.isPresent()) {
-        return facade.getType(expression.get());
-    } else {
-        return VoidType.INSTANCE;
-    }
-}).filter(x -> x != null && !x.isVoid() && !x.isNull()).findFirst() ==> java.util.stream.Stream.findFirst()
-  Line 432) returnStmts.stream().map(returnStmt -> {
-    Optional<Expression> expression = returnStmt.getExpression();
-    if (expression.isPresent()) {
-        return facade.getType(expression.get());
-    } else {
-        return VoidType.INSTANCE;
-    }
-}).filter(x -> x != null && !x.isVoid() && !x.isNull()) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
-  Line 432) returnStmts.stream().map(returnStmt -> {
-    Optional<Expression> expression = returnStmt.getExpression();
-    if (expression.isPresent()) {
-        return facade.getType(expression.get());
-    } else {
-        return VoidType.INSTANCE;
-    }
-}) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
-  Line 432) returnStmts.stream() ==> java.util.Collection.stream()
-  Line 434) returnStmt.getExpression() ==> com.github.javaparser.ast.stmt.ReturnStmt.getExpression()
-  Line 435) expression.isPresent() ==> java.util.Optional.isPresent()
-  Line 436) facade.getType(expression.get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node)
-  Line 436) expression.get() ==> java.util.Optional.get()
-  Line 441) x.isVoid() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isVoid()
-  Line 441) x.isNull() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isNull()
-  Line 454) functionalMethod.get().returnType() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.returnType()
-  Line 454) functionalMethod.get() ==> java.util.Optional.get()
-  Line 457) funcInterfaceCtx.addPair(formalType, actualType) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.addPair(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 459) funcInterfaceCtx.resolve(funcInterfaceCtx.addSingle(functionalInterfaceType)) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.resolve(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 459) funcInterfaceCtx.addSingle(functionalInterfaceType) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.addSingle(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 464) lambdaCtx.addPair(result, functionalTypeWithReturn) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.addPair(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 465) lambdaCtx.resolve(lambdaCtx.addSingle(result)) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.resolve(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 465) lambdaCtx.addSingle(result) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.addSingle(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 471) refMethod.getCorrespondingDeclaration().getParam(pos).getType() ==> com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration.getType()
-  Line 471) refMethod.getCorrespondingDeclaration().getParam(pos) ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getParam(int)
-  Line 471) refMethod.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 480) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 481) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 482) JavaParserSymbolDeclaration.getParamPos(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration.getParamPos(com.github.javaparser.ast.Node)
-  Line 483) facade.solve(callExpr, false) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.MethodCallExpr, boolean)
-  Line 484) refMethod.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 485) getParentNode(node).toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 485) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 485) callExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 485) callExpr.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
-  Line 487) logger.finest("getType on method reference expr " + refMethod.getCorrespondingDeclaration().getName()) ==> java.util.logging.Logger.finest(java.lang.String)
-  Line 487) refMethod.getCorrespondingDeclaration().getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
-  Line 487) refMethod.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 490) facade.solveMethodAsUsage(callExpr) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveMethodAsUsage(com.github.javaparser.ast.expr.MethodCallExpr)
-  Line 491) usage.getParamType(pos) ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.getParamType(int)
-  Line 493) JavaParserFactory.getContext(node, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 494) facade.solveGenericTypes(result, ctx, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveGenericTypes(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.core.resolution.Context, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 499) FunctionalInterfaceLogic.getFunctionalMethod(result) ==> com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic.getFunctionalMethod(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 500) functionalMethod.isPresent() ==> java.util.Optional.isPresent()
-  Line 504) facade.toMethodUsage(methodReferenceExpr).returnType() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.returnType()
-  Line 504) facade.toMethodUsage(methodReferenceExpr) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.toMethodUsage(com.github.javaparser.ast.expr.MethodReferenceExpr)
-  Line 505) functionalMethod.get().returnType() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.returnType()
-  Line 505) functionalMethod.get() ==> java.util.Optional.get()
-  Line 508) inferenceContext.addPair(formalType, actualType) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.addPair(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 509) inferenceContext.resolve(inferenceContext.addSingle(result)) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.resolve(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 509) inferenceContext.addSingle(result) ==> com.github.javaparser.symbolsolver.logic.InferenceContext.addSingle(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 515) refMethod.getCorrespondingDeclaration().getParam(pos).getType() ==> com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration.getType()
-  Line 515) refMethod.getCorrespondingDeclaration().getParam(pos) ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getParam(int)
-  Line 515) refMethod.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AnonymousClassDeclarationContext.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AnonymousClassDeclarationContext.txt
deleted file mode 100644
index b556156..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AnonymousClassDeclarationContext.txt
+++ /dev/null
@@ -1,96 +0,0 @@
-  Line 37) Preconditions.checkArgument(node.getAnonymousClassBody().isPresent(), "An anonymous class must have a body") ==> com.google.common.base.Preconditions.checkArgument(boolean, java.lang.Object)
-  Line 37) node.getAnonymousClassBody().isPresent() ==> java.util.Optional.isPresent()
-  Line 37) node.getAnonymousClassBody() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getAnonymousClassBody()
-  Line 47) myDeclaration.getDeclaredMethods().stream().filter(m -> m.getName().equals(name) && (!staticOnly || m.isStatic())).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
-  Line 47) myDeclaration.getDeclaredMethods().stream().filter(m -> m.getName().equals(name) && (!staticOnly || m.isStatic())) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
-  Line 47) myDeclaration.getDeclaredMethods().stream() ==> java.util.Collection.stream()
-  Line 47) myDeclaration.getDeclaredMethods() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getDeclaredMethods()
-  Line 50) m.getName().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 50) m.getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
-  Line 50) m.isStatic() ==> com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration.isStatic()
-  Line 51) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 53) Object.class.getCanonicalName().equals(myDeclaration.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
-  Line 53) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 53) myDeclaration.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getQualifiedName()
-  Line 54) myDeclaration.getAncestors() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getAncestors()
-  Line 56) MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 56) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 64) res.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 65) candidateMethods.add(res.getCorrespondingDeclaration()) ==> java.util.List.add(E)
-  Line 65) res.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 72) candidateMethods.isEmpty() ==> java.util.List.isEmpty()
-  Line 74) getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 74) getParent() ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.AbstractJavaParserContext.getParent()
-  Line 75) parentSolution.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 76) candidateMethods.add(parentSolution.getCorrespondingDeclaration()) ==> java.util.List.add(E)
-  Line 76) parentSolution.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 81) candidateMethods.isEmpty() ==> java.util.List.isEmpty()
-  Line 81) myDeclaration.getSuperTypeDeclaration().isInterface() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isInterface()
-  Line 81) myDeclaration.getSuperTypeDeclaration() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getSuperTypeDeclaration()
-  Line 83) MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 89) res.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 90) candidateMethods.add(res.getCorrespondingDeclaration()) ==> java.util.List.add(E)
-  Line 90) res.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 94) MethodResolutionLogic.findMostApplicable(candidateMethods, name, argumentsTypes, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.findMostApplicable(java.util.List<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration>, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 103) myDeclaration.findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
-  Line 107) typeDeclarations.stream().filter(internalType -> internalType.getName().getId().equals(name)).findFirst().map(internalType -> SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType))) ==> java.util.Optional.map(java.util.function.Function<? super T, ? extends U>)
-  Line 107) typeDeclarations.stream().filter(internalType -> internalType.getName().getId().equals(name)).findFirst() ==> java.util.stream.Stream.findFirst()
-  Line 107) typeDeclarations.stream().filter(internalType -> internalType.getName().getId().equals(name)) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
-  Line 107) typeDeclarations.stream() ==> java.util.Collection.stream()
-  Line 109) internalType.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 109) internalType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 109) internalType.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 112) SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 113) JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 113) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 115) exactMatch.isPresent() ==> java.util.Optional.isPresent()
-  Line 116) exactMatch.get() ==> java.util.Optional.get()
-  Line 120) typeDeclarations.stream().filter(internalType -> name.startsWith(String.format("%s.", internalType.getName()))).findFirst().map(internalType -> JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver)) ==> java.util.Optional.map(java.util.function.Function<? super T, ? extends U>)
-  Line 120) typeDeclarations.stream().filter(internalType -> name.startsWith(String.format("%s.", internalType.getName()))).findFirst() ==> java.util.stream.Stream.findFirst()
-  Line 120) typeDeclarations.stream().filter(internalType -> name.startsWith(String.format("%s.", internalType.getName()))) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
-  Line 120) typeDeclarations.stream() ==> java.util.Collection.stream()
-  Line 122) name.startsWith(String.format("%s.", internalType.getName())) ==> java.lang.String.startsWith(java.lang.String)
-  Line 122) String.format("%s.", internalType.getName()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
-  Line 122) internalType.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 125) JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 125) JavaParserFactory.getContext(internalType, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 127) name.substring(internalType.getName().getId().length() + 1) ==> java.lang.String.substring(int)
-  Line 127) internalType.getName().getId().length() ==> java.lang.String.length()
-  Line 127) internalType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 127) internalType.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 130) recursiveMatch.isPresent() ==> java.util.Optional.isPresent()
-  Line 131) recursiveMatch.get() ==> java.util.Optional.get()
-  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream().filter(type -> type.toString().equals(name)).findFirst().map(matchingType -> SymbolReference.solved(new JavaParserTypeParameter(new TypeParameter(matchingType.toString()), typeSolver))) ==> ERROR
-  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream().filter(type -> type.toString().equals(name)).findFirst() ==> ERROR
-  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream().filter(type -> type.toString().equals(name)) ==> ERROR
-  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream() ==> java.util.Collection.stream()
-  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()) ==> java.util.Optional.orElse(T)
-  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())) ==> java.util.Optional.map(java.util.function.Function<? super T, ? extends U>)
-  Line 135) wrappedNode.getTypeArguments() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getTypeArguments()
-  Line 138) ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>()) ==> java.util.Optional.orElse(T)
-  Line 138) ((NodeWithTypeArguments<?>) nodes).getTypeArguments() ==> com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments.getTypeArguments()
-  Line 142) type.toString().equals(name) ==> ERROR
-  Line 142) type.toString() ==> ERROR
-  Line 145) SymbolReference.solved(new JavaParserTypeParameter(new TypeParameter(matchingType.toString()), typeSolver)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 146) matchingType.toString() ==> ERROR
-  Line 149) typeArgumentsMatch.isPresent() ==> java.util.Optional.isPresent()
-  Line 150) typeArgumentsMatch.get() ==> java.util.Optional.get()
-  Line 154) myDeclaration.getAncestors() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getAncestors()
-  Line 156) ancestor.getTypeDeclaration().getName().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 156) ancestor.getTypeDeclaration().getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
-  Line 156) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 157) SymbolReference.solved(ancestor.getTypeDeclaration()) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 157) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 161) ancestor.getTypeDeclaration().internalTypes() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.internalTypes()
-  Line 161) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 162) internalTypeDeclaration.getName().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 162) internalTypeDeclaration.getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
-  Line 163) SymbolReference.solved(internalTypeDeclaration) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 171) getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 171) getParent() ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.AbstractJavaParserContext.getParent()
-  Line 177) Preconditions.checkArgument(typeSolver != null) ==> com.google.common.base.Preconditions.checkArgument(boolean)
-  Line 179) myDeclaration.hasVisibleField(name) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.hasVisibleField(java.lang.String)
-  Line 180) SymbolReference.solved(myDeclaration.getVisibleField(name)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 180) myDeclaration.getVisibleField(name) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getVisibleField(java.lang.String)
-  Line 183) getParent().solveSymbol(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveSymbol(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 183) getParent() ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.AbstractJavaParserContext.getParent()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CompilationUnitContext.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CompilationUnitContext.txt
deleted file mode 100644
index 532124e..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CompilationUnitContext.txt
+++ /dev/null
@@ -1,130 +0,0 @@
-  Line 49) name.contains(".") ==> java.lang.String.contains(java.lang.CharSequence)
-  Line 69) itName.contains(".") ==> java.lang.String.contains(java.lang.CharSequence)
-  Line 70) getType(itName) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getType(java.lang.String)
-  Line 71) getMember(itName) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getMember(java.lang.String)
-  Line 72) this.solveType(typeName, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 73) type.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 74) new SymbolSolver(typeSolver).solveSymbolInType(type.getCorrespondingDeclaration(), memberName) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String)
-  Line 74) type.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 81) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
-  Line 82) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
-  Line 83) importDecl.isStatic() ==> com.github.javaparser.ast.ImportDeclaration.isStatic()
-  Line 84) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
-  Line 85) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
-  Line 86) typeSolver.solveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 87) new SymbolSolver(typeSolver).solveSymbolInType(importedType, name) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String)
-  Line 88) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 92) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
-  Line 95) getMember(whole) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getMember(java.lang.String)
-  Line 96) getType(whole) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getType(java.lang.String)
-  Line 98) memberName.equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 99) typeSolver.solveType(typeName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 100) new SymbolSolver(typeSolver).solveSymbolInType(importedType, memberName) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String)
-  Line 107) SymbolReference.unsolved(ValueDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 112) wrappedNode.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
-  Line 113) wrappedNode.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
-  Line 114) type.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 114) type.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 114) type.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 116) SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration) type)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 116) JavaParserFacade.get(typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration) type) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 116) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 118) SymbolReference.solved(new JavaParserAnnotationDeclaration((AnnotationDeclaration) type, typeSolver)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 120) type.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 120) type.getClass() ==> java.lang.Object.getClass()
-  Line 126) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
-  Line 127) name.indexOf('.') ==> java.lang.String.indexOf(int)
-  Line 130) name.substring(0, dotPos) ==> java.lang.String.substring(int, int)
-  Line 133) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
-  Line 134) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
-  Line 135) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
-  Line 136) importDecl.getName().getQualifier().isPresent() ==> java.util.Optional.isPresent()
-  Line 136) importDecl.getName().getQualifier() ==> com.github.javaparser.ast.expr.Name.getQualifier()
-  Line 136) importDecl.getName() ==> com.github.javaparser.ast.ImportDeclaration.getName()
-  Line 137) importDecl.getName().getIdentifier().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 137) importDecl.getName().getIdentifier() ==> com.github.javaparser.ast.expr.Name.getIdentifier()
-  Line 137) importDecl.getName() ==> com.github.javaparser.ast.ImportDeclaration.getName()
-  Line 140) qName.endsWith("." + prefix) ==> java.lang.String.endsWith(java.lang.String)
-  Line 142) name.substring(dotPos) ==> java.lang.String.substring(int)
-  Line 147) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 148) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 149) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
-  Line 155) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
-  Line 156) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
-  Line 157) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
-  Line 158) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 159) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 160) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
-  Line 167) this.wrappedNode.getPackageDeclaration().isPresent() ==> java.util.Optional.isPresent()
-  Line 167) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
-  Line 168) this.wrappedNode.getPackageDeclaration().get().getName().toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 168) this.wrappedNode.getPackageDeclaration().get().getName() ==> com.github.javaparser.ast.PackageDeclaration.getName()
-  Line 168) this.wrappedNode.getPackageDeclaration().get() ==> java.util.Optional.get()
-  Line 168) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
-  Line 169) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 170) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 171) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
-  Line 176) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 177) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 178) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
-  Line 183) typeSolver.tryToSolveType("java.lang." + name) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 184) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 185) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
-  Line 189) isQualifiedName(name) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.isQualifiedName(java.lang.String)
-  Line 190) SymbolReference.adapt(typeSolver.tryToSolveType(name), com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
-  Line 190) typeSolver.tryToSolveType(name) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 192) SymbolReference.unsolved(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 197) type.getScope().isPresent() ==> java.util.Optional.isPresent()
-  Line 197) type.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 198) qName(type.getScope().get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.qName(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 198) type.getScope().get() ==> java.util.Optional.get()
-  Line 198) type.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 198) type.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 198) type.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 200) type.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 200) type.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 205) name.getQualifier().isPresent() ==> java.util.Optional.isPresent()
-  Line 205) name.getQualifier() ==> com.github.javaparser.ast.expr.Name.getQualifier()
-  Line 206) qName(name.getQualifier().get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.qName(com.github.javaparser.ast.expr.Name)
-  Line 206) name.getQualifier().get() ==> java.util.Optional.get()
-  Line 206) name.getQualifier() ==> com.github.javaparser.ast.expr.Name.getQualifier()
-  Line 206) name.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 208) name.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 213) qName.split("\\.") ==> java.lang.String.split(java.lang.String)
-  Line 218) qName.lastIndexOf('.') ==> java.lang.String.lastIndexOf(int)
-  Line 222) qName.substring(0, lastDot) ==> java.lang.String.substring(int, int)
-  Line 228) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
-  Line 229) importDecl.isStatic() ==> com.github.javaparser.ast.ImportDeclaration.isStatic()
-  Line 230) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
-  Line 231) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
-  Line 233) this.wrappedNode.getPackageDeclaration().isPresent() ==> java.util.Optional.isPresent()
-  Line 233) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
-  Line 234) this.wrappedNode.getPackageDeclaration().get().getName().getIdentifier().equals(packageName(importString)) ==> java.lang.String.equals(java.lang.Object)
-  Line 234) this.wrappedNode.getPackageDeclaration().get().getName().getIdentifier() ==> com.github.javaparser.ast.expr.Name.getIdentifier()
-  Line 234) this.wrappedNode.getPackageDeclaration().get().getName() ==> com.github.javaparser.ast.PackageDeclaration.getName()
-  Line 234) this.wrappedNode.getPackageDeclaration().get() ==> java.util.Optional.get()
-  Line 234) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
-  Line 234) packageName(importString) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.packageName(java.lang.String)
-  Line 235) this.wrappedNode.getTypes().stream().anyMatch(it -> it.getName().getIdentifier().equals(toSimpleName(importString))) ==> ERROR
-  Line 235) this.wrappedNode.getTypes().stream() ==> java.util.Collection.stream()
-  Line 235) this.wrappedNode.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
-  Line 235) it.getName().getIdentifier().equals(toSimpleName(importString)) ==> ERROR
-  Line 235) it.getName().getIdentifier() ==> ERROR
-  Line 235) it.getName() ==> ERROR
-  Line 235) toSimpleName(importString) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.toSimpleName(java.lang.String)
-  Line 238) SymbolReference.unsolved(MethodDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 241) typeSolver.solveType(importString) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 242) MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 244) method.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 248) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
-  Line 250) qName.equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 250) qName.endsWith("." + name) ==> java.lang.String.endsWith(java.lang.String)
-  Line 251) getType(qName) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getType(java.lang.String)
-  Line 252) typeSolver.solveType(typeName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 253) MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 254) method.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 261) SymbolReference.unsolved(MethodDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
-  Line 269) qName.lastIndexOf('.') ==> java.lang.String.lastIndexOf(int)
-  Line 273) qName.substring(0, index) ==> java.lang.String.substring(int, int)
-  Line 278) qName.lastIndexOf('.') ==> java.lang.String.lastIndexOf(int)
-  Line 282) qName.substring(index + 1) ==> java.lang.String.substring(int)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnonymousClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnonymousClassDeclaration.txt
deleted file mode 100644
index a195f82..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnonymousClassDeclaration.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-  Line 37) UUID.randomUUID() ==> java.util.UUID.randomUUID()
-  Line 44) JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver).solveType(wrappedNode.getType().getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 44) JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver).solveType(wrappedNode.getType().getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 44) JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 44) wrappedNode.getParentNode().get() ==> java.util.Optional.get()
-  Line 44) wrappedNode.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
-  Line 45) wrappedNode.getType().getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 45) wrappedNode.getType().getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 45) wrappedNode.getType() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getType()
-  Line 54) wrappedNode.getAnonymousClassBody().get().stream().filter(node -> memberClass.isAssignableFrom(node.getClass())).map(node -> (T) node).collect(Collectors.toList()) ==> ERROR
-  Line 54) wrappedNode.getAnonymousClassBody().get().stream().filter(node -> memberClass.isAssignableFrom(node.getClass())).map(node -> (T) node) ==> ERROR
-  Line 54) wrappedNode.getAnonymousClassBody().get().stream().filter(node -> memberClass.isAssignableFrom(node.getClass())) ==> ERROR
-  Line 54) wrappedNode.getAnonymousClassBody().get().stream() ==> java.util.Collection.stream()
-  Line 54) wrappedNode.getAnonymousClassBody().get() ==> java.util.Optional.get()
-  Line 54) wrappedNode.getAnonymousClassBody() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getAnonymousClassBody()
-  Line 58) memberClass.isAssignableFrom(node.getClass()) ==> ERROR
-  Line 58) node.getClass() ==> ERROR
-  Line 60) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 65) typeSolver.solveType(Object.class.getCanonicalName()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 65) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 70) superTypeDeclaration.asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 76) superTypeDeclaration.asReferenceType().getAncestors().stream().filter(type -> type.getTypeDeclaration().isInterface()).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
-  Line 76) superTypeDeclaration.asReferenceType().getAncestors().stream().filter(type -> type.getTypeDeclaration().isInterface()) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
-  Line 76) superTypeDeclaration.asReferenceType().getAncestors().stream() ==> java.util.Collection.stream()
-  Line 76) superTypeDeclaration.asReferenceType().getAncestors() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAncestors()
-  Line 76) superTypeDeclaration.asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 79) type.getTypeDeclaration().isInterface() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isInterface()
-  Line 79) type.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 80) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class).stream().map(ctor -> new JavaParserConstructorDeclaration(this, ctor, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
-  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class).stream().map(ctor -> new JavaParserConstructorDeclaration(this, ctor, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
-  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class).stream() ==> java.util.Collection.stream()
-  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
-  Line 89) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 100) ImmutableList.<ReferenceType>builder().add(getSuperClass()).addAll(superTypeDeclaration.asReferenceType().getAncestors()).build() ==> com.google.common.collect.ImmutableList.Builder.build()
-  Line 100) ImmutableList.<ReferenceType>builder().add(getSuperClass()).addAll(superTypeDeclaration.asReferenceType().getAncestors()) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
-  Line 100) ImmutableList.<ReferenceType>builder().add(getSuperClass()) ==> com.google.common.collect.ImmutableList.Builder.add(E...)
-  Line 100) ImmutableList.<ReferenceType>builder() ==> com.google.common.collect.ImmutableList.builder()
-  Line 102) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getSuperClass()
-  Line 103) superTypeDeclaration.asReferenceType().getAncestors() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAncestors()
-  Line 103) superTypeDeclaration.asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class).stream().flatMap(field -> field.getVariables().stream().map(variable -> new JavaParserFieldDeclaration(variable, typeSolver))).collect(Collectors.toList()) ==> ERROR
-  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class).stream().flatMap(field -> field.getVariables().stream().map(variable -> new JavaParserFieldDeclaration(variable, typeSolver))) ==> java.util.stream.Stream.flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>)
-  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class).stream() ==> java.util.Collection.stream()
-  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
-  Line 114) field.getVariables().stream().map(variable -> new JavaParserFieldDeclaration(variable, typeSolver)) ==> ERROR
-  Line 114) field.getVariables().stream() ==> ERROR
-  Line 114) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
-  Line 117) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 120) getSuperClass().getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
-  Line 120) getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 120) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getSuperClass()
-  Line 123) getInterfaces().stream().flatMap(inteface -> inteface.getTypeDeclaration().getAllFields().stream()).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
-  Line 123) getInterfaces().stream().flatMap(inteface -> inteface.getTypeDeclaration().getAllFields().stream()) ==> java.util.stream.Stream.flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>)
-  Line 123) getInterfaces().stream() ==> java.util.Collection.stream()
-  Line 123) getInterfaces() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getInterfaces()
-  Line 124) inteface.getTypeDeclaration().getAllFields().stream() ==> java.util.Collection.stream()
-  Line 124) inteface.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
-  Line 124) inteface.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 125) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields).addAll(superClassFields).addAll(interfaceFields).build() ==> com.google.common.collect.ImmutableList.Builder.build()
-  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields).addAll(superClassFields).addAll(interfaceFields) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
-  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields).addAll(superClassFields) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
-  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
-  Line 128) ImmutableList.<FieldDeclaration>builder() ==> com.google.common.collect.ImmutableList.builder()
-  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class).stream().map(method -> new JavaParserMethodDeclaration(method, typeSolver)).collect(Collectors.toSet()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
-  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class).stream().map(method -> new JavaParserMethodDeclaration(method, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
-  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class).stream() ==> java.util.Collection.stream()
-  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
-  Line 142) Collectors.toSet() ==> java.util.stream.Collectors.toSet()
-  Line 162) Helper.getPackageName(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.getPackageName(com.github.javaparser.ast.Node)
-  Line 167) Helper.getClassName("", wrappedNode) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.getClassName(java.lang.String, com.github.javaparser.ast.Node)
-  Line 172) Helper.containerName(getParentNode(wrappedNode)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.containerName(com.github.javaparser.ast.Node)
-  Line 172) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 173) containerName.isEmpty() ==> java.lang.String.isEmpty()
-  Line 174) getName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getName()
-  Line 176) getName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getName()
-  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class).stream().map(typeMember -> JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember)).collect(Collectors.toSet()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
-  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class).stream().map(typeMember -> JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
-  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class).stream() ==> java.util.Collection.stream()
-  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
-  Line 185) JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 185) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 186) Collectors.toSet() ==> java.util.stream.Collectors.toSet()
-  Line 196) Lists.newArrayList() ==> com.google.common.collect.Lists.newArrayList()
-  Line 201) this.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 201) this.getClass() ==> java.lang.Object.getClass()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt
deleted file mode 100644
index af627c4..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt
+++ /dev/null
@@ -1,139 +0,0 @@
-  Line 64) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
-  Line 79) getClass() ==> java.lang.Object.getClass()
-  Line 79) o.getClass() ==> java.lang.Object.getClass()
-  Line 83) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
-  Line 90) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
-  Line 107) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 110) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
-  Line 111) fields.add(new JavaParserFieldDeclaration(vd, typeSolver)) ==> java.util.ArrayList.add(E)
-  Line 116) this.getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 116) this.getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
-  Line 118) fields.addAll(superclass.getAllFields()) ==> java.util.ArrayList.addAll(java.util.Collection<? extends E>)
-  Line 118) superclass.getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
-  Line 120) getInterfaces().forEach(interf -> interf.getTypeDeclaration().getAllFields().forEach(f -> {
-    fields.add(f);
-})) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
-  Line 120) getInterfaces() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getInterfaces()
-  Line 120) interf.getTypeDeclaration().getAllFields().forEach(f -> {
-    fields.add(f);
-}) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
-  Line 120) interf.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
-  Line 120) interf.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 121) fields.add(f) ==> java.util.ArrayList.add(E)
-  Line 132) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
-  Line 133) ctx.solveMethod(name, parameterTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 138) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 147) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 147) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 152) wrappedNode.getExtendedTypes().isEmpty() ==> com.github.javaparser.ast.NodeList.isEmpty()
-  Line 152) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 153) object() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.object()
-  Line 155) toReferenceType(wrappedNode.getExtendedTypes().get(0)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 155) wrappedNode.getExtendedTypes().get(0) ==> com.github.javaparser.ast.NodeList.get(int)
-  Line 155) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 162) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 163) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 164) interfaces.add(toReferenceType(t)) ==> java.util.List.add(E)
-  Line 164) toReferenceType(t) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 173) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 176) declared.add(new JavaParserConstructorDeclaration(this, constructorDeclaration, typeSolver)) ==> java.util.List.add(E)
-  Line 179) declared.isEmpty() ==> java.util.List.isEmpty()
-  Line 181) ImmutableList.of(new DefaultConstructorDeclaration(this)) ==> com.google.common.collect.ImmutableList.of(E)
-  Line 189) wrappedNode.getAnnotations() ==> com.github.javaparser.ast.body.BodyDeclaration.getAnnotations()
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName) ==> java.lang.String.equals(java.lang.Object)
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 190) annotationExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 190) annotationExpr.getName() ==> com.github.javaparser.ast.expr.AnnotationExpr.getName()
-  Line 199) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
-  Line 204) javaParserTypeAdapter.getPackageName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getPackageName()
-  Line 209) javaParserTypeAdapter.getClassName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getClassName()
-  Line 214) javaParserTypeAdapter.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getQualifiedName()
-  Line 219) javaParserTypeAdapter.isAssignableBy(other) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 224) javaParserTypeAdapter.isAssignableBy(type) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 230) this.getQualifiedName().equals(other.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
-  Line 230) this.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getQualifiedName()
-  Line 230) other.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 233) getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 233) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
-  Line 236) Object.class.getCanonicalName().equals(superclass.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
-  Line 236) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 236) superclass.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 239) superclass.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 244) this.wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 245) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 246) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
-  Line 247) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 263) this.wrappedNode.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 263) this.wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 263) this.wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 264) SymbolReference.solved(this) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 266) javaParserTypeAdapter.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 267) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 271) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 272) name.startsWith(prefix) ==> java.lang.String.startsWith(java.lang.String)
-  Line 272) name.length() ==> java.lang.String.length()
-  Line 272) prefix.length() ==> java.lang.String.length()
-  Line 273) new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 273) name.substring(prefix.length()) ==> java.lang.String.substring(int)
-  Line 273) prefix.length() ==> java.lang.String.length()
-  Line 276) getContext().getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 276) getContext().getParent() ==> com.github.javaparser.symbolsolver.core.resolution.Context.getParent()
-  Line 276) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
-  Line 282) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
-  Line 284) ancestors.add(superclass) ==> java.util.List.add(E)
-  Line 286) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 287) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 288) toReferenceType(implemented) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 289) ancestors.add(ancestor) ==> java.util.List.add(E)
-  Line 298) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 300) methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)) ==> java.util.Set.add(E)
-  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> ERROR
-  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> ERROR
-  Line 308) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
-  Line 308) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
-  Line 310) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 324) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
-  Line 324) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.TypeDeclaration.getModifiers()
-  Line 333) typeSolver.solveType(Object.class.getCanonicalName()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 333) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 339) this.wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 341) res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member)) ==> java.util.Set.add(E)
-  Line 341) JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 341) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 349) javaParserTypeAdapter.containerType() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.containerType()
-  Line 357) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 357) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 358) classOrInterfaceType.getScope().isPresent() ==> java.util.Optional.isPresent()
-  Line 358) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 360) classOrInterfaceType.getScope().get().toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 360) classOrInterfaceType.getScope().get() ==> java.util.Optional.get()
-  Line 360) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 362) solveType(className, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 363) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 364) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 365) localScope.isPresent() ==> java.util.Optional.isPresent()
-  Line 366) localScope.get().getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 366) localScope.get().getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 366) localScope.get() ==> java.util.Optional.get()
-  Line 366) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 366) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 367) solveType(localName, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 370) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 371) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 371) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 373) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
-  Line 373) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 374) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 374) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> ERROR
-  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> ERROR
-  Line 376) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
-  Line 376) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
-  Line 376) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 377) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> ERROR
-  Line 377) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 378) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 379) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 379) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration_J9.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration_J9.txt
deleted file mode 100644
index df92d78..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration_J9.txt
+++ /dev/null
@@ -1,139 +0,0 @@
-  Line 64) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
-  Line 79) getClass() ==> java.lang.Object.getClass()
-  Line 79) o.getClass() ==> java.lang.Object.getClass()
-  Line 83) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
-  Line 90) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
-  Line 107) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 110) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
-  Line 111) fields.add(new JavaParserFieldDeclaration(vd, typeSolver)) ==> java.util.ArrayList.add(E)
-  Line 116) this.getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 116) this.getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
-  Line 118) fields.addAll(superclass.getAllFields()) ==> java.util.ArrayList.addAll(java.util.Collection<? extends E>)
-  Line 118) superclass.getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
-  Line 120) getInterfaces().forEach(interf -> interf.getTypeDeclaration().getAllFields().forEach(f -> {
-    fields.add(f);
-})) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
-  Line 120) getInterfaces() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getInterfaces()
-  Line 120) interf.getTypeDeclaration().getAllFields().forEach(f -> {
-    fields.add(f);
-}) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
-  Line 120) interf.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
-  Line 120) interf.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 121) fields.add(f) ==> java.util.ArrayList.add(E)
-  Line 132) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
-  Line 133) ctx.solveMethod(name, parameterTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 138) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 147) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 147) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 152) wrappedNode.getExtendedTypes().isEmpty() ==> com.github.javaparser.ast.NodeList.isEmpty()
-  Line 152) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 153) object() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.object()
-  Line 155) toReferenceType(wrappedNode.getExtendedTypes().get(0)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 155) wrappedNode.getExtendedTypes().get(0) ==> com.github.javaparser.ast.NodeList.get(int)
-  Line 155) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 162) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 163) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 164) interfaces.add(toReferenceType(t)) ==> java.util.List.add(E)
-  Line 164) toReferenceType(t) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 173) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 176) declared.add(new JavaParserConstructorDeclaration(this, constructorDeclaration, typeSolver)) ==> java.util.List.add(E)
-  Line 179) declared.isEmpty() ==> java.util.List.isEmpty()
-  Line 181) ImmutableList.of(new DefaultConstructorDeclaration(this)) ==> java.util.List.of(E...)
-  Line 189) wrappedNode.getAnnotations() ==> com.github.javaparser.ast.body.BodyDeclaration.getAnnotations()
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName) ==> java.lang.String.equals(java.lang.Object)
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 190) solveType(annotationExpr.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 190) annotationExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 190) annotationExpr.getName() ==> com.github.javaparser.ast.expr.AnnotationExpr.getName()
-  Line 199) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
-  Line 204) javaParserTypeAdapter.getPackageName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getPackageName()
-  Line 209) javaParserTypeAdapter.getClassName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getClassName()
-  Line 214) javaParserTypeAdapter.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getQualifiedName()
-  Line 219) javaParserTypeAdapter.isAssignableBy(other) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 224) javaParserTypeAdapter.isAssignableBy(type) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 230) this.getQualifiedName().equals(other.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
-  Line 230) this.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getQualifiedName()
-  Line 230) other.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 233) getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 233) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
-  Line 236) Object.class.getCanonicalName().equals(superclass.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
-  Line 236) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 236) superclass.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 239) superclass.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 244) this.wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 245) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 246) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
-  Line 247) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 263) this.wrappedNode.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 263) this.wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 263) this.wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 264) SymbolReference.solved(this) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 266) javaParserTypeAdapter.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 267) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 271) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 272) name.startsWith(prefix) ==> java.lang.String.startsWith(java.lang.String)
-  Line 272) name.length() ==> java.lang.String.length()
-  Line 272) prefix.length() ==> java.lang.String.length()
-  Line 273) new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 273) name.substring(prefix.length()) ==> java.lang.String.substring(int)
-  Line 273) prefix.length() ==> java.lang.String.length()
-  Line 276) getContext().getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 276) getContext().getParent() ==> com.github.javaparser.symbolsolver.core.resolution.Context.getParent()
-  Line 276) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
-  Line 282) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
-  Line 284) ancestors.add(superclass) ==> java.util.List.add(E)
-  Line 286) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 287) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 288) toReferenceType(implemented) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 289) ancestors.add(ancestor) ==> java.util.List.add(E)
-  Line 298) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 300) methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)) ==> java.util.Set.add(E)
-  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> ERROR
-  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> ERROR
-  Line 308) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
-  Line 308) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
-  Line 310) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 324) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
-  Line 324) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.TypeDeclaration.getModifiers()
-  Line 333) typeSolver.solveType(Object.class.getCanonicalName()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
-  Line 333) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 339) this.wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 341) res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member)) ==> java.util.Set.add(E)
-  Line 341) JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 341) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 349) javaParserTypeAdapter.containerType() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.containerType()
-  Line 357) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 357) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 358) classOrInterfaceType.getScope().isPresent() ==> java.util.Optional.isPresent()
-  Line 358) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 360) classOrInterfaceType.getScope().get().toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 360) classOrInterfaceType.getScope().get() ==> java.util.Optional.get()
-  Line 360) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 362) solveType(className, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 363) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 364) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
-  Line 365) localScope.isPresent() ==> java.util.Optional.isPresent()
-  Line 366) localScope.get().getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 366) localScope.get().getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 366) localScope.get() ==> java.util.Optional.get()
-  Line 366) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 366) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 367) solveType(localName, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 370) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 371) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 371) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 373) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
-  Line 373) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 374) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 374) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> ERROR
-  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> ERROR
-  Line 376) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
-  Line 376) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
-  Line 376) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 377) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> ERROR
-  Line 377) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 378) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 379) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 379) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserConstructorDeclaration.txt
deleted file mode 100644
index 5bbbf3e..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserConstructorDeclaration.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-  Line 48) this.wrappedNode.getParameters().size() ==> com.github.javaparser.ast.NodeList.size()
-  Line 48) this.wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
-  Line 53) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserConstructorDeclaration.getNumberOfParams()
-  Line 54) String.format("No param with index %d. Number of params: %d", i, getNumberOfParams()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
-  Line 54) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserConstructorDeclaration.getNumberOfParams()
-  Line 56) wrappedNode.getParameters().get(i) ==> com.github.javaparser.ast.NodeList.get(int)
-  Line 56) wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
-  Line 61) this.classDeclaration.getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
-  Line 75) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
-  Line 75) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.CallableDeclaration.getModifiers()
-  Line 80) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList()) ==> ERROR
-  Line 80) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)) ==> ERROR
-  Line 80) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
-  Line 80) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getTypeParameters()
-  Line 80) Collectors.toList() ==> java.util.stream.Collectors.toList()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserInterfaceDeclaration.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserInterfaceDeclaration.txt
deleted file mode 100644
index 02a1607..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserInterfaceDeclaration.txt
+++ /dev/null
@@ -1,120 +0,0 @@
-  Line 52) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
-  Line 63) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 65) methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)) ==> java.util.Set.add(E)
-  Line 72) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 82) getClass() ==> java.lang.Object.getClass()
-  Line 82) o.getClass() ==> java.lang.Object.getClass()
-  Line 86) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
-  Line 93) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
-  Line 98) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 98) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 108) wrappedNode.getAnnotations() ==> com.github.javaparser.ast.body.BodyDeclaration.getAnnotations()
-  Line 109) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName) ==> java.lang.String.equals(java.lang.Object)
-  Line 109) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 109) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 109) solveType(annotationExpr.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 109) annotationExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 109) annotationExpr.getName() ==> com.github.javaparser.ast.expr.AnnotationExpr.getName()
-  Line 124) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 125) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 126) interfaces.add(new ReferenceTypeImpl(solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration().asInterface(), typeSolver)) ==> java.util.List.add(E)
-  Line 126) solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration().asInterface() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asInterface()
-  Line 126) solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 126) solveType(t.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 126) t.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 126) t.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 134) javaParserTypeAdapter.getPackageName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getPackageName()
-  Line 139) javaParserTypeAdapter.getClassName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getClassName()
-  Line 144) javaParserTypeAdapter.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getQualifiedName()
-  Line 149) javaParserTypeAdapter.isAssignableBy(other) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 154) javaParserTypeAdapter.isAssignableBy(type) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 160) this.getQualifiedName().equals(other.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
-  Line 160) this.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.getQualifiedName()
-  Line 160) other.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 163) this.wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 164) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 165) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
-  Line 166) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 172) this.wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 173) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 174) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
-  Line 175) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
-  Line 192) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 195) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
-  Line 196) fields.add(new JavaParserFieldDeclaration(vd, typeSolver)) ==> java.util.ArrayList.add(E)
-  Line 201) getAncestors().forEach(a -> {
-    if (a.getTypeDeclaration() != this) {
-        fields.addAll(a.getTypeDeclaration().getAllFields());
-    }
-}) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
-  Line 201) getAncestors() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.getAncestors()
-  Line 202) a.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 203) fields.addAll(a.getTypeDeclaration().getAllFields()) ==> java.util.ArrayList.addAll(java.util.Collection<? extends E>)
-  Line 203) a.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
-  Line 203) a.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
-  Line 220) this.wrappedNode.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 220) this.wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 220) this.wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 221) SymbolReference.solved(this) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
-  Line 223) javaParserTypeAdapter.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 224) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 228) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
-  Line 229) name.startsWith(prefix) ==> java.lang.String.startsWith(java.lang.String)
-  Line 229) name.length() ==> java.lang.String.length()
-  Line 229) prefix.length() ==> java.lang.String.length()
-  Line 230) new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 230) name.substring(prefix.length()) ==> java.lang.String.substring(int)
-  Line 230) prefix.length() ==> java.lang.String.length()
-  Line 233) getContext().getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 233) getContext().getParent() ==> com.github.javaparser.symbolsolver.core.resolution.Context.getParent()
-  Line 233) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.getContext()
-  Line 239) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 240) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
-  Line 241) ancestors.add(toReferenceType(extended)) ==> java.util.List.add(E)
-  Line 241) toReferenceType(extended) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 244) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 245) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
-  Line 246) ancestors.add(toReferenceType(implemented)) ==> java.util.List.add(E)
-  Line 246) toReferenceType(implemented) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
-  Line 254) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
-  Line 255) Collections.emptyList() ==> java.util.Collections.emptyList()
-  Line 257) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> ERROR
-  Line 257) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> ERROR
-  Line 257) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
-  Line 257) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
-  Line 259) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 274) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
-  Line 274) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.TypeDeclaration.getModifiers()
-  Line 280) this.wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
-  Line 282) res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member)) ==> java.util.Set.add(E)
-  Line 282) JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
-  Line 282) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 290) javaParserTypeAdapter.containerType() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.containerType()
-  Line 299) classOrInterfaceType.toString().indexOf('.') ==> java.lang.String.indexOf(int)
-  Line 299) classOrInterfaceType.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 300) typeSolver.tryToSolveType(classOrInterfaceType.toString()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
-  Line 300) classOrInterfaceType.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 302) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 303) solveType(classOrInterfaceType.toString(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 303) classOrInterfaceType.toString() ==> com.github.javaparser.ast.Node.toString()
-  Line 305) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 306) solveType(classOrInterfaceType.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 306) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 306) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 308) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
-  Line 309) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 309) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
-  Line 311) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
-  Line 311) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 312) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 312) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
-  Line 314) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> ERROR
-  Line 314) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> ERROR
-  Line 314) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
-  Line 314) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
-  Line 314) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
-  Line 315) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> ERROR
-  Line 315) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 316) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 317) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
-  Line 317) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserMethodDeclaration.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserMethodDeclaration.txt
deleted file mode 100644
index 7efa56d..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserMethodDeclaration.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-  Line 58) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 59) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 62) JavaParserFactory.toTypeDeclaration(getParentNode(wrappedNode), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.toTypeDeclaration(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 62) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 68) JavaParserFacade.get(typeSolver).convert(wrappedNode.getType(), getContext()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
-  Line 68) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 68) wrappedNode.getType() ==> com.github.javaparser.ast.body.MethodDeclaration.getType()
-  Line 68) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration.getContext()
-  Line 73) wrappedNode.getParameters().size() ==> com.github.javaparser.ast.NodeList.size()
-  Line 73) wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
-  Line 78) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration.getNumberOfParams()
-  Line 79) String.format("No param with index %d. Number of params: %d", i, getNumberOfParams()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
-  Line 79) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration.getNumberOfParams()
-  Line 81) wrappedNode.getParameters().get(i) ==> com.github.javaparser.ast.NodeList.get(int)
-  Line 81) wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
-  Line 89) new MethodDeclarationCommonLogic(this, typeSolver).resolveTypeVariables(context, parameterTypes) ==> com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic.resolveTypeVariables(com.github.javaparser.symbolsolver.core.resolution.Context, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>)
-  Line 93) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 98) wrappedNode.getBody().isPresent() ==> java.util.Optional.isPresent()
-  Line 98) wrappedNode.getBody() ==> com.github.javaparser.ast.body.MethodDeclaration.getBody()
-  Line 103) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 103) wrappedNode.getName() ==> com.github.javaparser.ast.body.CallableDeclaration.getName()
-  Line 123) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList()) ==> ERROR
-  Line 123) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)) ==> ERROR
-  Line 123) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
-  Line 123) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getTypeParameters()
-  Line 123) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 128) wrappedNode.isDefault() ==> com.github.javaparser.ast.body.MethodDeclaration.isDefault()
-  Line 133) wrappedNode.isStatic() ==> com.github.javaparser.ast.nodeTypes.modifiers.NodeWithStaticModifier.isStatic()
-  Line 147) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
-  Line 147) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.CallableDeclaration.getModifiers()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeParameter.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeParameter.txt
deleted file mode 100644
index da6454b..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeParameter.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-  Line 56) Collections.emptySet() ==> java.util.Collections.emptySet()
-  Line 60) getContext().solveMethod(name, parameterTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 60) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContext()
-  Line 70) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
-  Line 77) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
-  Line 78) typeSolver.hashCode() ==> java.lang.Object.hashCode()
-  Line 84) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
-  Line 84) wrappedNode.getName() ==> com.github.javaparser.ast.type.TypeParameter.getName()
-  Line 89) isAssignableBy(new ReferenceTypeImpl(other, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 94) getContainer() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainer()
-  Line 96) ((ReferenceTypeDeclaration) container).getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
-  Line 98) ((JavaParserConstructorDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
-  Line 100) ((JavaParserMethodDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
-  Line 106) getContainer() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainer()
-  Line 108) ((ReferenceTypeDeclaration) container).getId() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getId()
-  Line 110) ((JavaParserConstructorDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
-  Line 112) ((JavaParserMethodDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
-  Line 118) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 121) JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 121) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 124) jpConstructorDeclaration.getAncestorOfType(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class) ==> com.github.javaparser.HasParentNode.getAncestorOfType(java.lang.Class<N>)
-  Line 125) jpTypeDeclaration.isPresent() ==> java.util.Optional.isPresent()
-  Line 126) JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration.get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
-  Line 126) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 126) jpTypeDeclaration.get() ==> java.util.Optional.get()
-  Line 127) typeDeclaration.isClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isClass()
-  Line 128) typeDeclaration.asClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asClass()
-  Line 140) String.format("%s.%s", getContainerQualifiedName(), getName()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
-  Line 140) getContainerQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainerQualifiedName()
-  Line 140) getName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getName()
-  Line 145) wrappedNode.getTypeBound().stream().map((astB) -> toBound(astB, typeSolver)).collect(Collectors.toList()) ==> ERROR
-  Line 145) wrappedNode.getTypeBound().stream().map((astB) -> toBound(astB, typeSolver)) ==> ERROR
-  Line 145) wrappedNode.getTypeBound().stream() ==> java.util.Collection.stream()
-  Line 145) wrappedNode.getTypeBound() ==> com.github.javaparser.ast.type.TypeParameter.getTypeBound()
-  Line 145) toBound(astB, typeSolver) ==> ERROR
-  Line 145) Collectors.toList() ==> java.util.stream.Collectors.toList()
-  Line 149) JavaParserFacade.get(typeSolver).convertToUsage(classOrInterfaceType, classOrInterfaceType) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
-  Line 149) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
-  Line 150) Bound.extendsBound(type) ==> com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration.Bound.extendsBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 199) Collections.emptyList() ==> java.util.Collections.emptyList()
-  Line 213) wrappedNode.getName() ==> com.github.javaparser.ast.type.TypeParameter.getName()
-  Line 213) wrappedNode.getTypeBound() ==> com.github.javaparser.ast.type.TypeParameter.getTypeBound()
-  Line 218) getContainer() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainer()
-  Line 220) Optional.of((ReferenceTypeDeclaration) container) ==> java.util.Optional.of(T)
-  Line 222) Optional.empty() ==> java.util.Optional.empty()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_VariableSymbolDeclarator.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_VariableSymbolDeclarator.txt
deleted file mode 100644
index e0d28d3..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_VariableSymbolDeclarator.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-  Line 38) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
-  Line 45) wrappedNode.getVariables().stream().map(v -> JavaParserSymbolDeclaration.localVar(v, typeSolver)).collect(Collectors.toCollection(() -> new LinkedList<>())) ==> ERROR
-  Line 45) wrappedNode.getVariables().stream().map(v -> JavaParserSymbolDeclaration.localVar(v, typeSolver)) ==> ERROR
-  Line 45) wrappedNode.getVariables().stream() ==> java.util.Collection.stream()
-  Line 45) wrappedNode.getVariables() ==> com.github.javaparser.ast.expr.VariableDeclarationExpr.getVariables()
-  Line 46) JavaParserSymbolDeclaration.localVar(v, typeSolver) ==> ERROR
-  Line 48) Collectors.toCollection(() -> new LinkedList<>()) ==> java.util.stream.Collectors.toCollection(java.util.function.Supplier<C>)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType_J9.txt b/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType_J9.txt
deleted file mode 100644
index 57a7c2a..0000000
--- a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType_J9.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-  Line 32) Byte.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 32) ImmutableList.of() ==> com.google.common.collect.ImmutableList.of()
-  Line 33) Short.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 33) ImmutableList.of(BYTE) ==> java.util.List.of(E...)
-  Line 34) Character.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 34) ImmutableList.of() ==> com.google.common.collect.ImmutableList.of()
-  Line 35) Integer.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 35) ImmutableList.of(BYTE, SHORT, CHAR) ==> java.util.List.of(E...)
-  Line 36) Long.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 36) ImmutableList.of(BYTE, SHORT, INT, CHAR) ==> java.util.List.of(E...)
-  Line 37) Boolean.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 37) ImmutableList.of() ==> com.google.common.collect.ImmutableList.of()
-  Line 38) Float.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 38) ImmutableList.of(LONG, INT, SHORT, BYTE, CHAR) ==> java.util.List.of(E...)
-  Line 39) Double.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
-  Line 39) ImmutableList.of(FLOAT, LONG, INT, SHORT, BYTE, CHAR) ==> java.util.List.of(E...)
-  Line 40) ImmutableList.of(INT, BOOLEAN, LONG, CHAR, FLOAT, DOUBLE, SHORT, BYTE) ==> java.util.List.of(E...)
-  Line 57) name.toLowerCase() ==> java.lang.String.toLowerCase()
-  Line 59) ptu.describe().equals(name) ==> java.lang.String.equals(java.lang.Object)
-  Line 59) ptu.describe() ==> com.github.javaparser.symbolsolver.model.typesystem.PrimitiveType.describe()
-  Line 104) other.isPrimitive() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isPrimitive()
-  Line 105) promotionTypes.contains(other) ==> java.util.List.contains(java.lang.Object)
-  Line 106) other.isReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isReferenceType()
-  Line 107) other.asReferenceType().getQualifiedName().equals(boxTypeQName) ==> java.lang.String.equals(java.lang.Object)
-  Line 107) other.asReferenceType().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getQualifiedName()
-  Line 107) other.asReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asReferenceType()
-  Line 111) other.asReferenceType().getQualifiedName().equals(promotion.boxTypeQName) ==> java.lang.String.equals(java.lang.Object)
-  Line 111) other.asReferenceType().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getQualifiedName()
-  Line 111) other.asReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asReferenceType()
-  Line 116) other.isConstraint() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isConstraint()
-  Line 117) this.isAssignableBy(other.asConstraintType().getBound()) ==> com.github.javaparser.symbolsolver.model.typesystem.PrimitiveType.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
-  Line 117) other.asConstraintType().getBound() ==> com.github.javaparser.symbolsolver.model.typesystem.LambdaConstraintType.getBound()
-  Line 117) other.asConstraintType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asConstraintType()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/solveMethodDeclaredInEnum/MyEnum.jar b/javaparser-symbol-solver-testing/src/test/resources/solveMethodDeclaredInEnum/MyEnum.jar
new file mode 100644
index 0000000..f270628
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/solveMethodDeclaredInEnum/MyEnum.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/resources/solveMethodDeclaredInEnum/MyEnum.java b/javaparser-symbol-solver-testing/src/test/resources/solveMethodDeclaredInEnum/MyEnum.java
new file mode 100644
index 0000000..63dd595
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/solveMethodDeclaredInEnum/MyEnum.java
@@ -0,0 +1,6 @@
+enum MyEnum {
+    CONST;
+
+    public void method() {
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/resources/test-artifact-1.0.0.jar b/javaparser-symbol-solver-testing/src/test/resources/test-artifact-1.0.0.jar
new file mode 100644
index 0000000..57b818d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/resources/test-artifact-1.0.0.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_CommentsInserter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_CommentsInserter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_CommentsInserter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_CommentsInserter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_JavaParser.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_JavaParser.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_JavaParser.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_JavaParser.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParseProblemException.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParseProblemException.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParseProblemException.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParseProblemException.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParseResult.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParseResult.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParseResult.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParseResult.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParseStart.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParseStart.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParseStart.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParseStart.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParserConfiguration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParserConfiguration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ParserConfiguration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ParserConfiguration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Position.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Position.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Position.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Position.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Problem.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Problem.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Problem.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Problem.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Providers.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Providers.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Providers.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Providers.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Range.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Range.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_Range.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_Range.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_AccessSpecifier.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_AccessSpecifier.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_AccessSpecifier.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_AccessSpecifier.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_ArrayBracketPair.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_ArrayBracketPair.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_ArrayBracketPair.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_ArrayBracketPair.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_ArrayCreationLevel.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_ArrayCreationLevel.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_ArrayCreationLevel.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_ArrayCreationLevel.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_CompilationUnit.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_CompilationUnit.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_CompilationUnit.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_CompilationUnit.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Example.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Example.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Example.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Example.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_ImportDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_ImportDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_ImportDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_ImportDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Modifier.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Modifier.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Modifier.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Modifier.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Modifier.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Modifier_J9.txt
similarity index 100%
copy from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Modifier.txt
copy to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Modifier_J9.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Node.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Node.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_Node.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_Node.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_PackageDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_PackageDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_PackageDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_PackageDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_UserDataKey.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_UserDataKey.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_UserDataKey.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_UserDataKey.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_Parameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_Parameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_Parameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_Parameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_BlockComment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_BlockComment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_BlockComment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_BlockComment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_Comment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_Comment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_Comment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_Comment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_JavadocComment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_JavadocComment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_JavadocComment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_JavadocComment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_LineComment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_LineComment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_comments_LineComment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_comments_LineComment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_AssignExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_AssignExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_AssignExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_AssignExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_CastExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_CastExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_CastExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_CastExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ClassExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ClassExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ClassExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ClassExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_Expression.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_Expression.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_Expression.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_Expression.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_NameExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_NameExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_NameExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_NameExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_SuperExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_SuperExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_SuperExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_SuperExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ThisExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ThisExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_ThisExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_ThisExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_TypeExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_TypeExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_TypeExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_TypeExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithAnnotations.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithAnnotations.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithAnnotations.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithAnnotations.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBlockStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBlockStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBlockStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBlockStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBody.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBody.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBody.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithBody.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithElementType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithElementType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithElementType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithElementType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithExtends.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithExtends.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithExtends.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithExtends.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithImplements.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithImplements.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithImplements.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithImplements.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithJavaDoc.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithJavaDoc.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithJavaDoc.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithJavaDoc.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithMembers.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithMembers.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithMembers.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithMembers.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithModifiers.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithModifiers.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithModifiers.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithModifiers.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithName.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithName.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithName.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithName.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithParameters.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithParameters.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithParameters.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithParameters.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithStatements.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithStatements.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithStatements.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithStatements.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithThrowable.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithThrowable.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithThrowable.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithThrowable.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithTypeArguments.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithTypeArguments.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithTypeArguments.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithTypeArguments.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithVariables.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithVariables.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_nodeTypes_NodeWithVariables.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_nodeTypes_NodeWithVariables.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_CatchClause.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_CatchClause.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_CatchClause.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_CatchClause.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_DoStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_DoStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_DoStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_DoStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ForStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ForStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ForStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ForStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_IfStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_IfStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_IfStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_IfStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_Statement.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_Statement.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_Statement.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_Statement.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_TryStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_TryStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_TryStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_TryStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_ArrayType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_ArrayType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_ArrayType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_ArrayType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_IntersectionType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_IntersectionType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_IntersectionType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_IntersectionType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_PrimitiveType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_PrimitiveType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_PrimitiveType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_PrimitiveType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_ReferenceType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_ReferenceType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_ReferenceType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_ReferenceType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_Type.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_Type.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_Type.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_Type.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_TypeParameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_TypeParameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_TypeParameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_TypeParameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_UnionType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_UnionType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_UnionType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_UnionType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_UnknownType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_UnknownType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_UnknownType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_UnknownType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_VoidType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_VoidType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_VoidType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_VoidType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_WildcardType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_WildcardType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_type_WildcardType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_type_WildcardType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
similarity index 100%
copy from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
copy to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_TreeVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_TreeVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_TreeVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_TreeVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
similarity index 100%
copy from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
copy to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_ClassUtils.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_ClassUtils.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_ClassUtils.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_ClassUtils.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_Pair.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_Pair.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_Pair.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_Pair.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_PositionUtils.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_PositionUtils.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_PositionUtils.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_PositionUtils.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_Utils.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_Utils.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_methodcalls_expected_output/com_github_javaparser_utils_Utils.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/expected_output/com_github_javaparser_utils_Utils.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources/com/github/javaparser/Provider.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources/com/github/javaparser/Provider.java
index bfd9da8..13d71c5 100644
--- a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources/com/github/javaparser/Provider.java
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_new_src/javaparser-generated-sources/com/github/javaparser/Provider.java
@@ -22,7 +22,7 @@
      * Reads characters into an array
      * @param buffer  Destination buffer
      * @param offset   Offset at which to start storing characters
-     * @param length   The maximum possible number of characters to read
+     * @param len      The maximum possible number of characters to read
      * @return The number of characters read, or -1 if all read
      * @exception  IOException
      */
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ASTHelper.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ASTHelper.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ASTHelper.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ASTHelper.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_JavaParser.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_JavaParser.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_JavaParser.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_JavaParser.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_Position.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_Position.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_Position.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_Position.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_PositionUtils.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_PositionUtils.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_PositionUtils.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_PositionUtils.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_SourcesHelper.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_SourcesHelper.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_SourcesHelper.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_SourcesHelper.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_AccessSpecifier.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_AccessSpecifier.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_AccessSpecifier.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_AccessSpecifier.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_CompilationUnit.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_CompilationUnit.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_CompilationUnit.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_CompilationUnit.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_DocumentableNode.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_DocumentableNode.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_DocumentableNode.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_DocumentableNode.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_ImportDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_ImportDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_ImportDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_ImportDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_NamedNode.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_NamedNode.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_NamedNode.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_NamedNode.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_Node.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_Node.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_Node.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_Node.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_PackageDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_PackageDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_PackageDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_PackageDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_TreeVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_TreeVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_TreeVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_TreeVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_TypeParameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_TypeParameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_TypeParameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_TypeParameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_AnnotableNode.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_AnnotableNode.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_AnnotableNode.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_AnnotableNode.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_AnnotationDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_AnnotationMemberDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_BaseParameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_BaseParameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_BaseParameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_BaseParameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_BodyDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_ClassOrInterfaceDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_ConstructorDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EmptyMemberDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EmptyTypeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EnumConstantDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_EnumDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_FieldDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_InitializerDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_MethodDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_ModifierSet.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_ModifierSet.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_ModifierSet.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_ModifierSet.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_MultiTypeParameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_MultiTypeParameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_MultiTypeParameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_MultiTypeParameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_Parameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_Parameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_Parameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_Parameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_TypeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_VariableDeclarator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_VariableDeclaratorId.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_WithDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_WithDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_body_WithDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_body_WithDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_BlockComment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_BlockComment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_BlockComment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_BlockComment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_Comment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_Comment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_Comment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_Comment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_CommentsCollection.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_CommentsParser.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_CommentsParser.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_CommentsParser.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_CommentsParser.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_JavadocComment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_JavadocComment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_JavadocComment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_JavadocComment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_LineComment.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_LineComment.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_comments_LineComment.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_comments_LineComment.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_AnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ArrayAccessExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ArrayCreationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ArrayInitializerExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_AssignExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_AssignExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_AssignExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_AssignExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_BinaryExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_BooleanLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_CastExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_CastExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_CastExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_CastExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_CharLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ClassExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ClassExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ClassExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ClassExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ConditionalExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_DoubleLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_EnclosedExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_Expression.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_Expression.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_Expression.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_Expression.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_FieldAccessExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_InstanceOfExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_IntegerLiteralMinValueExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LambdaExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LongLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_LongLiteralMinValueExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MarkerAnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MemberValuePair.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MethodCallExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_MethodReferenceExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_NameExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_NameExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_NameExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_NameExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_NormalAnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_NullLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ObjectCreationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_QualifiedNameExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_SingleMemberAnnotationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_StringLiteralExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_SuperExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_SuperExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_SuperExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_SuperExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ThisExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ThisExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_ThisExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_ThisExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_TypeExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_TypeExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_TypeExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_TypeExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_UnaryExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_expr_VariableDeclarationExpr.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_internal_Utils.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_internal_Utils.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_internal_Utils.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_internal_Utils.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_AssertStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_BlockStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_BreakStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_CatchClause.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_CatchClause.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_CatchClause.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_CatchClause.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ContinueStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_DoStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_DoStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_DoStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_DoStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_EmptyStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ExplicitConstructorInvocationStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ExpressionStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ForStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ForStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ForStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ForStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ForeachStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_IfStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_IfStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_IfStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_IfStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_LabeledStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ReturnStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_Statement.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_Statement.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_Statement.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_Statement.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_SwitchEntryStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_SwitchStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_SynchronizedStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_ThrowStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_TryStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_TryStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_TryStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_TryStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_TypeDeclarationStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_stmt_WhileStmt.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_ClassOrInterfaceType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_PrimitiveType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_PrimitiveType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_PrimitiveType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_PrimitiveType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_ReferenceType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_ReferenceType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_ReferenceType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_ReferenceType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_Type.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_Type.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_Type.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_Type.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_UnknownType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_UnknownType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_UnknownType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_UnknownType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_VoidType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_VoidType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_VoidType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_VoidType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_WildcardType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_WildcardType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_type_WildcardType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_type_WildcardType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_CloneVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_DumpVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_EqualsVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_GenericVisitorAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_ModifierVisitorAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javaparser_expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javaparser_src/expected_output/com_github_javaparser_ast_visitor_VoidVisitorAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_SourceFileInfoExtractor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_SourceFileInfoExtractor.txt
new file mode 100644
index 0000000..a0f71ce
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_SourceFileInfoExtractor.txt
@@ -0,0 +1,77 @@
+  Line 100) JavaParserFacade.get(typeSolver).getTypeDeclaration(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+  Line 100) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 101) typeDeclaration.isClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isClass()
+  Line 102) out.println("\n[ Class " + typeDeclaration.getQualifiedName() + " ]") ==> java.io.PrintStream.println(java.lang.String)
+  Line 102) typeDeclaration.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 103) typeDeclaration.asClass().getAllSuperClasses() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getAllSuperClasses()
+  Line 103) typeDeclaration.asClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asClass()
+  Line 104) out.println("  superclass: " + sc.getQualifiedName()) ==> java.io.PrintStream.println(java.lang.String)
+  Line 104) sc.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getQualifiedName()
+  Line 106) typeDeclaration.asClass().getAllInterfaces() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getAllInterfaces()
+  Line 106) typeDeclaration.asClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asClass()
+  Line 107) out.println("  interface: " + sc.getQualifiedName()) ==> java.io.PrintStream.println(java.lang.String)
+  Line 107) sc.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getQualifiedName()
+  Line 114) solveTypeDecl((ClassOrInterfaceDeclaration) node) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveTypeDecl(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+  Line 116) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 116) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 117) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 118) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 120) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 120) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 122) JavaParserFacade.get(typeSolver).getType(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node)
+  Line 122) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 123) out.println("  Line " + node.getRange().get().begin.line + ") " + node + " ==> " + ref.describe()) ==> java.io.PrintStream.println(java.lang.String)
+  Line 123) node.getRange().get() ==> java.util.Optional.get()
+  Line 123) node.getRange() ==> com.github.javaparser.ast.Node.getRange()
+  Line 123) ref.describe() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.describe()
+  Line 127) err.println(upe.getMessage()) ==> java.io.PrintStream.println(java.lang.String)
+  Line 127) upe.getMessage() ==> java.lang.Throwable.getMessage()
+  Line 131) err.println(re.getMessage()) ==> java.io.PrintStream.println(java.lang.String)
+  Line 131) re.getMessage() ==> java.lang.Throwable.getMessage()
+  Line 140) out.println("  Line " + node.getBegin().get().line + ") " + node + " ==> " + toString((MethodCallExpr) node)) ==> java.io.PrintStream.println(java.lang.String)
+  Line 140) node.getBegin().get() ==> java.util.Optional.get()
+  Line 140) node.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
+  Line 140) toString((MethodCallExpr) node) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.toString(com.github.javaparser.ast.expr.MethodCallExpr)
+  Line 142) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 143) solveMethodCalls(child) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveMethodCalls(com.github.javaparser.ast.Node)
+  Line 149) toString(JavaParserFacade.get(typeSolver).solve(node)) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.toString(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration>)
+  Line 149) JavaParserFacade.get(typeSolver).solve(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.MethodCallExpr)
+  Line 149) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 152) System.err.println("Error resolving call at L" + node.getBegin().get().line + ": " + node) ==> java.io.PrintStream.println(java.lang.String)
+  Line 152) node.getBegin().get() ==> java.util.Optional.get()
+  Line 152) node.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
+  Line 153) e.printStackTrace() ==> java.lang.Throwable.printStackTrace()
+  Line 160) methodDeclarationSymbolReference.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 161) methodDeclarationSymbolReference.getCorrespondingDeclaration().getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
+  Line 161) methodDeclarationSymbolReference.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 169) collectAllNodes(node, nodes) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.collectAllNodes(com.github.javaparser.ast.Node, java.util.List<com.github.javaparser.ast.Node>)
+  Line 170) nodes.sort((n1, n2) -> n1.getBegin().get().compareTo(n2.getBegin().get())) ==> java.util.List.sort(java.util.Comparator<? super E>)
+  Line 170) n1.getBegin().get().compareTo(n2.getBegin().get()) ==> com.github.javaparser.Position.compareTo(com.github.javaparser.Position)
+  Line 170) n1.getBegin().get() ==> java.util.Optional.get()
+  Line 170) n1.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
+  Line 170) n2.getBegin().get() ==> java.util.Optional.get()
+  Line 170) n2.getBegin() ==> com.github.javaparser.ast.nodeTypes.NodeWithRange.getBegin()
+  Line 175) nodes.add(node) ==> java.util.List.add(E)
+  Line 176) node.getChildNodes().forEach(c -> collectAllNodes(c, nodes)) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
+  Line 176) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 176) collectAllNodes(c, nodes) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.collectAllNodes(com.github.javaparser.ast.Node, java.util.List<com.github.javaparser.ast.Node>)
+  Line 180) file.isDirectory() ==> java.io.File.isDirectory()
+  Line 181) file.listFiles() ==> java.io.File.listFiles()
+  Line 182) solve(f) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solve(java.io.File)
+  Line 185) file.getName().endsWith(".java") ==> java.lang.String.endsWith(java.lang.String)
+  Line 185) file.getName() ==> java.io.File.getName()
+  Line 187) out.println("- parsing " + file.getAbsolutePath()) ==> java.io.PrintStream.println(java.lang.String)
+  Line 187) file.getAbsolutePath() ==> java.io.File.getAbsolutePath()
+  Line 189) JavaParser.parse(file) ==> com.github.javaparser.JavaParser.parse(java.io.File)
+  Line 190) collectAllNodes(cu) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.collectAllNodes(com.github.javaparser.ast.Node)
+  Line 191) nodes.forEach(n -> solve(n)) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
+  Line 191) solve(n) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solve(com.github.javaparser.ast.Node)
+  Line 197) file.isDirectory() ==> java.io.File.isDirectory()
+  Line 198) file.listFiles() ==> java.io.File.listFiles()
+  Line 199) solveMethodCalls(f) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveMethodCalls(java.io.File)
+  Line 202) file.getName().endsWith(".java") ==> java.lang.String.endsWith(java.lang.String)
+  Line 202) file.getName() ==> java.io.File.getName()
+  Line 204) out.println("- parsing " + file.getAbsolutePath()) ==> java.io.PrintStream.println(java.lang.String)
+  Line 204) file.getAbsolutePath() ==> java.io.File.getAbsolutePath()
+  Line 206) JavaParser.parse(file) ==> com.github.javaparser.JavaParser.parse(java.io.File)
+  Line 207) solveMethodCalls(cu) ==> com.github.javaparser.symbolsolver.SourceFileInfoExtractor.solveMethodCalls(com.github.javaparser.ast.Node)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_Context.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_Context.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_Context.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_Context.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_ContextHelper.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_ContextHelper.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_ContextHelper.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_core_resolution_ContextHelper.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_declarations_common_MethodDeclarationCommonLogic.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_declarations_common_MethodDeclarationCommonLogic.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_declarations_common_MethodDeclarationCommonLogic.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_declarations_common_MethodDeclarationCommonLogic.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparser_Navigator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparser_Navigator.txt
new file mode 100644
index 0000000..4511f8e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparser_Navigator.txt
@@ -0,0 +1,104 @@
+  Line 44) node.getParentNode().orElse(null) ==> java.util.Optional.orElse(T)
+  Line 44) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
+  Line 49) cu.getTypes().isEmpty() ==> com.github.javaparser.ast.NodeList.isEmpty()
+  Line 49) cu.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
+  Line 50) Optional.empty() ==> java.util.Optional.empty()
+  Line 53) getOuterTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getOuterTypeName(java.lang.String)
+  Line 54) cu.getTypes().stream().filter((t) -> t.getName().getId().equals(typeName)).findFirst() ==> java.util.stream.Stream.findFirst()
+  Line 54) cu.getTypes().stream().filter((t) -> t.getName().getId().equals(typeName)) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 54) cu.getTypes().stream() ==> java.util.Collection.stream()
+  Line 54) cu.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
+  Line 54) t.getName().getId().equals(typeName) ==> java.lang.String.equals(java.lang.Object)
+  Line 54) t.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 54) t.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 56) getInnerTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getInnerTypeName(java.lang.String)
+  Line 57) type.isPresent() ==> java.util.Optional.isPresent()
+  Line 57) innerTypeName.isEmpty() ==> java.lang.String.isEmpty()
+  Line 58) findType(type.get(), innerTypeName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.body.TypeDeclaration<?>, java.lang.String)
+  Line 58) type.get() ==> java.util.Optional.get()
+  Line 64) getOuterTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getOuterTypeName(java.lang.String)
+  Line 66) Optional.empty() ==> java.util.Optional.empty()
+  Line 67) td.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 68) ((TypeDeclaration<?>) n).getName().getId().equals(typeName) ==> java.lang.String.equals(java.lang.Object)
+  Line 68) ((TypeDeclaration<?>) n).getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 68) ((TypeDeclaration<?>) n).getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 69) Optional.of((TypeDeclaration<?>) n) ==> java.util.Optional.of(T)
+  Line 73) getInnerTypeName(qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getInnerTypeName(java.lang.String)
+  Line 74) type.isPresent() ==> java.util.Optional.isPresent()
+  Line 74) innerTypeName.isEmpty() ==> java.lang.String.isEmpty()
+  Line 75) findType(type.get(), innerTypeName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.body.TypeDeclaration<?>, java.lang.String)
+  Line 75) type.get() ==> java.util.Optional.get()
+  Line 81) demandClassOrInterface(cu, qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.demandClassOrInterface(com.github.javaparser.ast.CompilationUnit, java.lang.String)
+  Line 82) cd.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
+  Line 89) findType(cu, qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.CompilationUnit, java.lang.String)
+  Line 90) res.isPresent() ==> java.util.Optional.isPresent()
+  Line 93) res.get() ==> java.util.Optional.get()
+  Line 96) res.get() ==> java.util.Optional.get()
+  Line 101) cd.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 104) md.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 104) md.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 104) md.getName() ==> com.github.javaparser.ast.body.CallableDeclaration.getName()
+  Line 119) cd.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 122) fd.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
+  Line 123) vd.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 123) vd.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 123) vd.getName() ==> com.github.javaparser.ast.body.VariableDeclarator.getName()
+  Line 135) nameExpr.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
+  Line 135) nameExpr.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 135) nameExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 135) nameExpr.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
+  Line 139) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 140) findNameExpression(child, name) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNameExpression(com.github.javaparser.ast.Node, java.lang.String)
+  Line 151) nameExpr.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 151) nameExpr.getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 151) nameExpr.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 155) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 156) findSimpleName(child, name) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findSimpleName(com.github.javaparser.ast.Node, java.lang.String)
+  Line 167) methodCallExpr.getName().getId().equals(methodName) ==> java.lang.String.equals(java.lang.Object)
+  Line 167) methodCallExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 167) methodCallExpr.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
+  Line 171) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 172) findMethodCall(child, methodName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findMethodCall(com.github.javaparser.ast.Node, java.lang.String)
+  Line 183) variableDeclarator.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 183) variableDeclarator.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 183) variableDeclarator.getName() ==> com.github.javaparser.ast.body.VariableDeclarator.getName()
+  Line 187) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 188) demandVariableDeclaration(child, name) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.demandVariableDeclaration(com.github.javaparser.ast.Node, java.lang.String)
+  Line 197) findType(compilationUnit, qualifiedName) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findType(com.github.javaparser.ast.CompilationUnit, java.lang.String)
+  Line 198) res.isPresent() ==> java.util.Optional.isPresent()
+  Line 201) res.get() ==> java.util.Optional.get()
+  Line 202) res.get().getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 202) res.get().getClass() ==> java.lang.Object.getClass()
+  Line 202) res.get() ==> java.util.Optional.get()
+  Line 204) res.get() ==> java.util.Optional.get()
+  Line 209) findSwitchHelper(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findSwitchHelper(com.github.javaparser.ast.Node)
+  Line 218) findNodeOfGivenClassHelper(node, clazz) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNodeOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>)
+  Line 228) findAllNodesOfGivenClassHelper(node, clazz, res) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findAllNodesOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>, java.util.List<N>)
+  Line 233) findNodeOfGivenClass(method, ReturnStmt.class) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNodeOfGivenClass(com.github.javaparser.ast.Node, java.lang.Class<N>)
+  Line 237) node.getParentNode().isPresent() ==> java.util.Optional.isPresent()
+  Line 237) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
+  Line 238) Optional.empty() ==> java.util.Optional.empty()
+  Line 239) clazz.isInstance(node.getParentNode().get()) ==> java.lang.Class.isInstance(java.lang.Object)
+  Line 239) node.getParentNode().get() ==> java.util.Optional.get()
+  Line 239) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
+  Line 240) Optional.of(clazz.cast(node.getParentNode().get())) ==> java.util.Optional.of(T)
+  Line 240) clazz.cast(node.getParentNode().get()) ==> java.lang.Class.cast(java.lang.Object)
+  Line 240) node.getParentNode().get() ==> java.util.Optional.get()
+  Line 240) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
+  Line 242) findAncestor(node.getParentNode().get(), clazz) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findAncestor(com.github.javaparser.ast.Node, java.lang.Class<N>)
+  Line 242) node.getParentNode().get() ==> java.util.Optional.get()
+  Line 242) node.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
+  Line 251) qualifiedName.split("\\.", 2) ==> java.lang.String.split(java.lang.String, int)
+  Line 255) qualifiedName.contains(".") ==> java.lang.String.contains(java.lang.CharSequence)
+  Line 256) qualifiedName.split("\\.", 2) ==> java.lang.String.split(java.lang.String, int)
+  Line 265) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 266) findSwitchHelper(child) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findSwitchHelper(com.github.javaparser.ast.Node)
+  Line 275) clazz.isInstance(node) ==> java.lang.Class.isInstance(java.lang.Object)
+  Line 276) clazz.cast(node) ==> java.lang.Class.cast(java.lang.Object)
+  Line 278) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 279) findNodeOfGivenClassHelper(child, clazz) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findNodeOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>)
+  Line 288) clazz.isInstance(node) ==> java.lang.Class.isInstance(java.lang.Object)
+  Line 289) collector.add(clazz.cast(node)) ==> java.util.List.add(E)
+  Line 289) clazz.cast(node) ==> java.lang.Class.cast(java.lang.Object)
+  Line 291) node.getChildNodes() ==> com.github.javaparser.ast.Node.getChildNodes()
+  Line 292) findAllNodesOfGivenClassHelper(child, clazz, collector) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.findAllNodesOfGivenClassHelper(com.github.javaparser.ast.Node, java.lang.Class<N>, java.util.List<N>)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_DefaultVisitorAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_DefaultVisitorAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_DefaultVisitorAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_DefaultVisitorAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt
new file mode 100644
index 0000000..041284d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt
@@ -0,0 +1,253 @@
+  Line 58) Logger.getLogger(JavaParserFacade.class.getCanonicalName()) ==> java.util.logging.Logger.getLogger(java.lang.String)
+  Line 58) JavaParserFacade.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 61) logger.setLevel(Level.INFO) ==> java.util.logging.Logger.setLevel(java.util.logging.Level)
+  Line 63) consoleHandler.setLevel(Level.INFO) ==> java.util.logging.Handler.setLevel(java.util.logging.Level)
+  Line 64) logger.addHandler(consoleHandler) ==> java.util.logging.Logger.addHandler(java.util.logging.Handler)
+  Line 75) typeSolver.getRoot() ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.getRoot()
+  Line 89) instances.computeIfAbsent(typeSolver, JavaParserFacade::new) ==> java.util.Map.computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>)
+  Line 96) instances.clear() ==> java.util.Map.clear()
+  Line 100) type.isTypeVariable() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isTypeVariable()
+  Line 101) context.solveGenericType(type.describe(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveGenericType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 101) type.describe() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.describe()
+  Line 102) solved.isPresent() ==> java.util.Optional.isPresent()
+  Line 103) solved.get() ==> java.util.Optional.get()
+  Line 107) type.isWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isWildcard()
+  Line 108) type.asWildcard().isExtends() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.isExtends()
+  Line 108) type.asWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asWildcard()
+  Line 108) type.asWildcard().isSuper() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.isSuper()
+  Line 108) type.asWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asWildcard()
+  Line 109) type.asWildcard() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asWildcard()
+  Line 110) solveGenericTypes(wildcardUsage.getBoundedType(), context, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveGenericTypes(com.github.javaparser.symbolsolver.model.typesystem.Type, com.github.javaparser.symbolsolver.core.resolution.Context, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 110) wildcardUsage.getBoundedType() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.getBoundedType()
+  Line 111) wildcardUsage.isExtends() ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.isExtends()
+  Line 112) Wildcard.extendsBound(boundResolved) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.extendsBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 114) Wildcard.superBound(boundResolved) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.superBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 126) symbolSolver.solveSymbol(nameExpr.getName().getId(), nameExpr) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbol(java.lang.String, com.github.javaparser.ast.Node)
+  Line 126) nameExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 126) nameExpr.getName() ==> com.github.javaparser.ast.expr.NameExpr.getName()
+  Line 130) symbolSolver.solveSymbol(nameExpr.getId(), nameExpr) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbol(java.lang.String, com.github.javaparser.ast.Node)
+  Line 130) nameExpr.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 135) solve((NameExpr) expr) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.NameExpr)
+  Line 137) expr.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 137) expr.getClass() ==> java.lang.Object.getClass()
+  Line 142) solve(methodCallExpr, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.MethodCallExpr, boolean)
+  Line 146) solve(objectCreationExpr, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.expr.ObjectCreationExpr, boolean)
+  Line 150) solve(explicitConstructorInvocationStmt, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solve(com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt, boolean)
+  Line 157) solveArguments(explicitConstructorInvocationStmt, explicitConstructorInvocationStmt.getArguments(), solveLambdas, argumentTypes, placeholders) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveArguments(com.github.javaparser.ast.Node, com.github.javaparser.ast.NodeList<com.github.javaparser.ast.expr.Expression>, boolean, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, java.util.List<com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder>)
+  Line 157) explicitConstructorInvocationStmt.getArguments() ==> com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt.getArguments()
+  Line 159) explicitConstructorInvocationStmt.getAncestorOfType(ClassOrInterfaceDeclaration.class) ==> com.github.javaparser.HasParentNode.getAncestorOfType(java.lang.Class<N>)
+  Line 160) optAncestor.isPresent() ==> java.util.Optional.isPresent()
+  Line 161) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 163) optAncestor.get() ==> java.util.Optional.get()
+  Line 165) explicitConstructorInvocationStmt.isThis() ==> com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt.isThis()
+  Line 166) JavaParserFacade.get(typeSolver).convert(classNode.getExtendedTypes(0), classNode) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 166) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 166) classNode.getExtendedTypes(0) ==> com.github.javaparser.ast.nodeTypes.NodeWithExtends.getExtendedTypes(int)
+  Line 167) classDecl.isReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isReferenceType()
+  Line 168) classDecl.asReferenceType().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 168) classDecl.asReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asReferenceType()
+  Line 171) JavaParserFactory.getContext(classNode, typeSolver).solveType(classNode.getNameAsString(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 171) JavaParserFactory.getContext(classNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 171) classNode.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithSimpleName.getNameAsString()
+  Line 172) sr.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 173) sr.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 177) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 179) ConstructorResolutionLogic.findMostApplicable(((ClassDeclaration) typeDecl).getConstructors(), argumentTypes, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic.findMostApplicable(java.util.List<com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration>, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 179) ((ClassDeclaration) typeDecl).getConstructors() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getConstructors()
+  Line 181) placeholder.setMethod(res) ==> com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder.setMethod(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration>)
+  Line 188) node.getClassExpr().isPresent() ==> java.util.Optional.isPresent()
+  Line 188) node.getClassExpr() ==> com.github.javaparser.ast.expr.ThisExpr.getClassExpr()
+  Line 190) node.getClassExpr().get().toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 190) node.getClassExpr().get() ==> java.util.Optional.get()
+  Line 190) node.getClassExpr() ==> com.github.javaparser.ast.expr.ThisExpr.getClassExpr()
+  Line 192) typeSolver.tryToSolveType(className) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 193) clazz.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 194) SymbolReference.solved(clazz.getCorrespondingDeclaration()) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 194) clazz.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 197) node.getAncestorOfType(CompilationUnit.class) ==> com.github.javaparser.HasParentNode.getAncestorOfType(java.lang.Class<N>)
+  Line 198) cu.isPresent() ==> java.util.Optional.isPresent()
+  Line 199) cu.get().getClassByName(className) ==> com.github.javaparser.ast.CompilationUnit.getClassByName(java.lang.String)
+  Line 199) cu.get() ==> java.util.Optional.get()
+  Line 200) classByName.isPresent() ==> java.util.Optional.isPresent()
+  Line 201) SymbolReference.solved(getTypeDeclaration(classByName.get())) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 201) getTypeDeclaration(classByName.get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+  Line 201) classByName.get() ==> java.util.Optional.get()
+  Line 205) SymbolReference.solved(getTypeDeclaration(findContainingTypeDecl(node))) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 205) getTypeDeclaration(findContainingTypeDecl(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
+  Line 205) findContainingTypeDecl(node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.findContainingTypeDecl(com.github.javaparser.ast.Node)
+  Line 215) solveArguments(objectCreationExpr, objectCreationExpr.getArguments(), solveLambdas, argumentTypes, placeholders) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveArguments(com.github.javaparser.ast.Node, com.github.javaparser.ast.NodeList<com.github.javaparser.ast.expr.Expression>, boolean, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, java.util.List<com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder>)
+  Line 215) objectCreationExpr.getArguments() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getArguments()
+  Line 217) JavaParserFacade.get(typeSolver).convert(objectCreationExpr.getType(), objectCreationExpr) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 217) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 217) objectCreationExpr.getType() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getType()
+  Line 218) classDecl.isReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isReferenceType()
+  Line 219) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 221) ConstructorResolutionLogic.findMostApplicable(((ClassDeclaration) classDecl.asReferenceType().getTypeDeclaration()).getConstructors(), argumentTypes, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic.findMostApplicable(java.util.List<com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration>, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 221) ((ClassDeclaration) classDecl.asReferenceType().getTypeDeclaration()).getConstructors() ==> com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration.getConstructors()
+  Line 221) classDecl.asReferenceType().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 221) classDecl.asReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.asReferenceType()
+  Line 223) placeholder.setMethod(res) ==> com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder.setMethod(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration>)
+  Line 233) argumentTypes.add(placeholder) ==> java.util.List.add(E)
+  Line 234) placeholders.add(placeholder) ==> java.util.List.add(E)
+  Line 237) argumentTypes.add(JavaParserFacade.get(typeSolver).getType(parameterValue, solveLambdas)) ==> java.util.List.add(E)
+  Line 237) JavaParserFacade.get(typeSolver).getType(parameterValue, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
+  Line 237) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 241) String.format("Unable to calculate the type of a parameter of a method call. Method call: %s, Parameter: %s", node, parameterValue) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
+  Line 256) solveArguments(methodCallExpr, methodCallExpr.getArguments(), solveLambdas, argumentTypes, placeholders) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.solveArguments(com.github.javaparser.ast.Node, com.github.javaparser.ast.NodeList<com.github.javaparser.ast.expr.Expression>, boolean, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, java.util.List<com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder>)
+  Line 256) methodCallExpr.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
+  Line 258) JavaParserFactory.getContext(methodCallExpr, typeSolver).solveMethod(methodCallExpr.getName().getId(), argumentTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 258) JavaParserFactory.getContext(methodCallExpr, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 258) methodCallExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 258) methodCallExpr.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
+  Line 260) placeholder.setMethod(res) ==> com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder.setMethod(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration>)
+  Line 266) JavaParserFactory.getContext(annotationExpr, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 267) context.solveType(annotationExpr.getNameAsString(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 267) annotationExpr.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
+  Line 268) typeDeclarationSymbolReference.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 269) typeDeclarationSymbolReference.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 270) SymbolReference.solved(annotationDeclaration) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 272) SymbolReference.unsolved(AnnotationDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 277) getType(node, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
+  Line 282) cacheWithLambdasSolved.containsKey(node) ==> java.util.Map.containsKey(java.lang.Object)
+  Line 283) getTypeConcrete(node, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
+  Line 285) cacheWithLambdasSolved.put(node, res) ==> java.util.Map.put(K, V)
+  Line 290) methodCallExpr.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
+  Line 291) cacheWithLambdasSolved.containsKey(arg) ==> java.util.Map.containsKey(java.lang.Object)
+  Line 292) getType(arg, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
+  Line 298) cacheWithLambdasSolved.remove(node) ==> java.util.Map.remove(java.lang.Object)
+  Line 299) cacheWithLambdasSolved.put(node, getType(node, true)) ==> java.util.Map.put(K, V)
+  Line 299) getType(node, true) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
+  Line 301) logger.finer("getType on " + node + " -> " + res) ==> java.util.logging.Logger.finer(java.lang.String)
+  Line 303) cacheWithLambdasSolved.get(node) ==> java.util.Map.get(java.lang.Object)
+  Line 305) find(cacheWithLambdasSolved, node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.find(java.util.Map<com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.ast.Node)
+  Line 306) res.isPresent() ==> java.util.Optional.isPresent()
+  Line 307) res.get() ==> java.util.Optional.get()
+  Line 309) find(cacheWithoutLambdasSolved, node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.find(java.util.Map<com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.ast.Node)
+  Line 310) res.isPresent() ==> java.util.Optional.isPresent()
+  Line 311) getTypeConcrete(node, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
+  Line 312) cacheWithoutLambdasSolved.put(node, resType) ==> java.util.Map.put(K, V)
+  Line 313) logger.finer("getType on " + node + " (no solveLambdas) -> " + res) ==> java.util.logging.Logger.finer(java.lang.String)
+  Line 316) res.get() ==> java.util.Optional.get()
+  Line 321) map.containsKey(node) ==> java.util.Map.containsKey(java.lang.Object)
+  Line 322) Optional.of(map.get(node)) ==> java.util.Optional.of(T)
+  Line 322) map.get(node) ==> java.util.Map.get(java.lang.Object)
+  Line 325) find(map, (LambdaExpr) node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.find(java.util.Map<com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.ast.expr.LambdaExpr)
+  Line 327) Optional.empty() ==> java.util.Optional.empty()
+  Line 338) map.keySet() ==> java.util.Map.keySet()
+  Line 341) keyLambdaExpr.toString().equals(lambdaExpr.toString()) ==> java.lang.String.equals(java.lang.Object)
+  Line 341) keyLambdaExpr.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 341) lambdaExpr.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 341) getParentNode(keyLambdaExpr) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 341) getParentNode(lambdaExpr) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 342) Optional.of(map.get(keyLambdaExpr)) ==> java.util.Optional.of(T)
+  Line 342) map.get(keyLambdaExpr) ==> java.util.Map.get(java.lang.Object)
+  Line 346) Optional.empty() ==> java.util.Optional.empty()
+  Line 350) methodReferenceExpr.getScope() ==> com.github.javaparser.ast.expr.MethodReferenceExpr.getScope()
+  Line 353) methodReferenceExpr.getScope() ==> com.github.javaparser.ast.expr.MethodReferenceExpr.getScope()
+  Line 354) typeExpr.getType() ==> com.github.javaparser.ast.expr.TypeExpr.getType()
+  Line 355) typeExpr.getType().getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 355) typeExpr.getType().getClass() ==> java.lang.Object.getClass()
+  Line 355) typeExpr.getType() ==> com.github.javaparser.ast.expr.TypeExpr.getType()
+  Line 357) typeExpr.getType() ==> com.github.javaparser.ast.expr.TypeExpr.getType()
+  Line 358) JavaParserFactory.getContext(classOrInterfaceType, typeSolver).solveType(classOrInterfaceType.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 358) JavaParserFactory.getContext(classOrInterfaceType, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 358) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 358) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 359) typeDeclarationSymbolReference.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream().filter(it -> it.getName().equals(methodReferenceExpr.getIdentifier())).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream().filter(it -> it.getName().equals(methodReferenceExpr.getIdentifier())) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream() ==> java.util.Collection.stream()
+  Line 362) ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllMethods()
+  Line 362) typeDeclarationSymbolReference.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 362) it.getName().equals(methodReferenceExpr.getIdentifier()) ==> java.lang.String.equals(java.lang.Object)
+  Line 362) it.getName() ==> com.github.javaparser.symbolsolver.model.methods.MethodUsage.getName()
+  Line 362) methodReferenceExpr.getIdentifier() ==> com.github.javaparser.ast.expr.MethodReferenceExpr.getIdentifier()
+  Line 362) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 363) methodUsages.size() ==> java.util.List.size()
+  Line 367) methodUsages.get(0) ==> java.util.List.get(int)
+  Line 374) getTypeConcrete(left, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
+  Line 375) getTypeConcrete(right, solveLambdas) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeConcrete(com.github.javaparser.ast.Node, boolean)
+  Line 376) rightType.isAssignableBy(leftType) ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 391) node.accept(typeExtractor, solveLambdas) ==> com.github.javaparser.ast.visitor.Visitable.accept(com.github.javaparser.ast.visitor.GenericVisitor<R, A>, A)
+  Line 399) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 402) findContainingTypeDecl(getParentNode(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.findContainingTypeDecl(com.github.javaparser.ast.Node)
+  Line 402) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 407) JavaParserFacade.get(typeSolver).convertToUsage(var.getType(), var) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 407) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 407) var.getType() ==> com.github.javaparser.ast.body.VariableDeclarator.getType()
+  Line 415) convertToUsage(type, JavaParserFactory.getContext(context, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 415) JavaParserFactory.getContext(context, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 419) convertToUsage(type, type) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 424) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 424) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 425) classOrInterfaceType.getScope().isPresent() ==> java.util.Optional.isPresent()
+  Line 425) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 426) qName(classOrInterfaceType.getScope().get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.qName(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 426) classOrInterfaceType.getScope().get() ==> java.util.Optional.get()
+  Line 426) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 435) qName(classOrInterfaceType) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.qName(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 436) context.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 437) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 440) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 441) Collections.emptyList() ==> java.util.Collections.emptyList()
+  Line 442) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
+  Line 442) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 443) classOrInterfaceType.getTypeArguments().get().stream().map((pt) -> convertToUsage(pt, context)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 443) classOrInterfaceType.getTypeArguments().get().stream().map((pt) -> convertToUsage(pt, context)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 443) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
+  Line 443) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
+  Line 443) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 443) convertToUsage(pt, context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 443) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 445) typeDeclaration.isTypeParameter() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isTypeParameter()
+  Line 450) javaParserTypeVariableDeclaration.asTypeParameter() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration.asTypeParameter()
+  Line 456) PrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) type).getType().name()) ==> com.github.javaparser.symbolsolver.model.typesystem.PrimitiveType.byName(java.lang.String)
+  Line 456) ((com.github.javaparser.ast.type.PrimitiveType) type).getType().name() ==> java.lang.Enum.name()
+  Line 456) ((com.github.javaparser.ast.type.PrimitiveType) type).getType() ==> com.github.javaparser.ast.type.PrimitiveType.getType()
+  Line 459) wildcardType.getExtendedTypes().isPresent() ==> java.util.Optional.isPresent()
+  Line 459) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
+  Line 459) wildcardType.getSuperTypes().isPresent() ==> java.util.Optional.isPresent()
+  Line 459) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
+  Line 460) Wildcard.extendsBound(convertToUsage(wildcardType.getExtendedTypes().get(), context)) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.extendsBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 460) convertToUsage(wildcardType.getExtendedTypes().get(), context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 460) wildcardType.getExtendedTypes().get() ==> java.util.Optional.get()
+  Line 460) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
+  Line 461) wildcardType.getExtendedTypes().isPresent() ==> java.util.Optional.isPresent()
+  Line 461) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
+  Line 461) wildcardType.getSuperTypes().isPresent() ==> java.util.Optional.isPresent()
+  Line 461) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
+  Line 462) Wildcard.superBound(convertToUsage(wildcardType.getSuperTypes().get(), context)) ==> com.github.javaparser.symbolsolver.model.typesystem.Wildcard.superBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 462) convertToUsage(wildcardType.getSuperTypes().get(), context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 462) wildcardType.getSuperTypes().get() ==> java.util.Optional.get()
+  Line 462) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
+  Line 463) wildcardType.getExtendedTypes().isPresent() ==> java.util.Optional.isPresent()
+  Line 463) wildcardType.getExtendedTypes() ==> com.github.javaparser.ast.type.WildcardType.getExtendedTypes()
+  Line 463) wildcardType.getSuperTypes().isPresent() ==> java.util.Optional.isPresent()
+  Line 463) wildcardType.getSuperTypes() ==> com.github.javaparser.ast.type.WildcardType.getSuperTypes()
+  Line 466) wildcardType.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 472) convertToUsage(jpArrayType.getComponentType(), context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 472) jpArrayType.getComponentType() ==> com.github.javaparser.ast.type.ArrayType.getComponentType()
+  Line 474) type.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 474) type.getClass() ==> java.lang.Object.getClass()
+  Line 480) convert(type, JavaParserFactory.getContext(node, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 480) JavaParserFactory.getContext(node, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 484) convertToUsage(type, context) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 489) call.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
+  Line 490) call.getArguments() ==> com.github.javaparser.ast.expr.MethodCallExpr.getArguments()
+  Line 493) params.add(getType(param, false)) ==> java.util.List.add(E)
+  Line 493) getType(param, false) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getType(com.github.javaparser.ast.Node, boolean)
+  Line 495) String.format("Error calculating the type of parameter %s of method call %s", param, call) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
+  Line 500) JavaParserFactory.getContext(call, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 501) context.solveMethodAsUsage(call.getName().getId(), params, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethodAsUsage(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 501) call.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 501) call.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
+  Line 502) methodUsage.isPresent() ==> java.util.Optional.isPresent()
+  Line 503) call.getName() ==> com.github.javaparser.ast.expr.MethodCallExpr.getName()
+  Line 504) call.getRange().get() ==> java.util.Optional.get()
+  Line 504) call.getRange() ==> com.github.javaparser.ast.Node.getRange()
+  Line 506) methodUsage.get() ==> java.util.Optional.get()
+  Line 510) JavaParserFactory.toTypeDeclaration(classOrInterfaceDeclaration, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.toTypeDeclaration(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 519) getTypeDeclaration((ClassOrInterfaceDeclaration) node) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+  Line 524) getTypeOfThisIn(getParentNode(node)) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeOfThisIn(com.github.javaparser.ast.Node)
+  Line 524) getParentNode(node) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 529) JavaParserFactory.toTypeDeclaration(typeDeclaration, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.toTypeDeclaration(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFactory.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFactory.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFactory.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFactory.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_LambdaArgumentTypePlaceholder.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_LambdaArgumentTypePlaceholder.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_LambdaArgumentTypePlaceholder.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_LambdaArgumentTypePlaceholder.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor_J9.txt
similarity index 100%
copy from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor.txt
copy to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_TypeExtractor_J9.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_UnsolvedSymbolException.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_UnsolvedSymbolException.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_UnsolvedSymbolException.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_UnsolvedSymbolException.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractJavaParserContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractJavaParserContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractJavaParserContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractJavaParserContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractMethodLikeDeclarationContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractMethodLikeDeclarationContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractMethodLikeDeclarationContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AbstractMethodLikeDeclarationContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AnonymousClassDeclarationContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AnonymousClassDeclarationContext.txt
new file mode 100644
index 0000000..48a7d82
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_AnonymousClassDeclarationContext.txt
@@ -0,0 +1,96 @@
+  Line 37) Preconditions.checkArgument(node.getAnonymousClassBody().isPresent(), "An anonymous class must have a body") ==> com.google.common.base.Preconditions.checkArgument(boolean, java.lang.Object)
+  Line 37) node.getAnonymousClassBody().isPresent() ==> java.util.Optional.isPresent()
+  Line 37) node.getAnonymousClassBody() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getAnonymousClassBody()
+  Line 47) myDeclaration.getDeclaredMethods().stream().filter(m -> m.getName().equals(name) && (!staticOnly || m.isStatic())).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 47) myDeclaration.getDeclaredMethods().stream().filter(m -> m.getName().equals(name) && (!staticOnly || m.isStatic())) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 47) myDeclaration.getDeclaredMethods().stream() ==> java.util.Collection.stream()
+  Line 47) myDeclaration.getDeclaredMethods() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getDeclaredMethods()
+  Line 50) m.getName().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 50) m.getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
+  Line 50) m.isStatic() ==> com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration.isStatic()
+  Line 51) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 53) Object.class.getCanonicalName().equals(myDeclaration.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
+  Line 53) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 53) myDeclaration.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getQualifiedName()
+  Line 54) myDeclaration.getAncestors() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getAncestors()
+  Line 56) MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 56) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 64) res.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 65) candidateMethods.add(res.getCorrespondingDeclaration()) ==> java.util.List.add(E)
+  Line 65) res.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 72) candidateMethods.isEmpty() ==> java.util.List.isEmpty()
+  Line 74) getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 74) getParent() ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.AbstractJavaParserContext.getParent()
+  Line 75) parentSolution.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 76) candidateMethods.add(parentSolution.getCorrespondingDeclaration()) ==> java.util.List.add(E)
+  Line 76) parentSolution.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 81) candidateMethods.isEmpty() ==> java.util.List.isEmpty()
+  Line 81) myDeclaration.getSuperTypeDeclaration().isInterface() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isInterface()
+  Line 81) myDeclaration.getSuperTypeDeclaration() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getSuperTypeDeclaration()
+  Line 83) MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 89) res.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 90) candidateMethods.add(res.getCorrespondingDeclaration()) ==> java.util.List.add(E)
+  Line 90) res.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 94) MethodResolutionLogic.findMostApplicable(candidateMethods, name, argumentsTypes, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.findMostApplicable(java.util.List<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration>, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 103) myDeclaration.findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
+  Line 107) typeDeclarations.stream().filter(internalType -> internalType.getName().getId().equals(name)).findFirst().map(internalType -> SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType))) ==> java.util.Optional.map(java.util.function.Function<? super T, ? extends U>)
+  Line 107) typeDeclarations.stream().filter(internalType -> internalType.getName().getId().equals(name)).findFirst() ==> java.util.stream.Stream.findFirst()
+  Line 107) typeDeclarations.stream().filter(internalType -> internalType.getName().getId().equals(name)) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 107) typeDeclarations.stream() ==> java.util.Collection.stream()
+  Line 109) internalType.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 109) internalType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 109) internalType.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 112) SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 113) JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
+  Line 113) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 115) exactMatch.isPresent() ==> java.util.Optional.isPresent()
+  Line 116) exactMatch.get() ==> java.util.Optional.get()
+  Line 120) typeDeclarations.stream().filter(internalType -> name.startsWith(String.format("%s.", internalType.getName()))).findFirst().map(internalType -> JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver)) ==> java.util.Optional.map(java.util.function.Function<? super T, ? extends U>)
+  Line 120) typeDeclarations.stream().filter(internalType -> name.startsWith(String.format("%s.", internalType.getName()))).findFirst() ==> java.util.stream.Stream.findFirst()
+  Line 120) typeDeclarations.stream().filter(internalType -> name.startsWith(String.format("%s.", internalType.getName()))) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 120) typeDeclarations.stream() ==> java.util.Collection.stream()
+  Line 122) name.startsWith(String.format("%s.", internalType.getName())) ==> java.lang.String.startsWith(java.lang.String)
+  Line 122) String.format("%s.", internalType.getName()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
+  Line 122) internalType.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 125) JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 125) JavaParserFactory.getContext(internalType, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 127) name.substring(internalType.getName().getId().length() + 1) ==> java.lang.String.substring(int)
+  Line 127) internalType.getName().getId().length() ==> java.lang.String.length()
+  Line 127) internalType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 127) internalType.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 130) recursiveMatch.isPresent() ==> java.util.Optional.isPresent()
+  Line 131) recursiveMatch.get() ==> java.util.Optional.get()
+  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream().filter(type -> type.toString().equals(name)).findFirst().map(matchingType -> SymbolReference.solved(new JavaParserTypeParameter(new TypeParameter(matchingType.toString()), typeSolver))) ==> java.util.Optional.map(java.util.function.Function<? super T, ? extends U>)
+  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream().filter(type -> type.toString().equals(name)).findFirst() ==> java.util.stream.Stream.findFirst()
+  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream().filter(type -> type.toString().equals(name)) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()).stream() ==> java.util.Collection.stream()
+  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())).orElse(new NodeList<>()) ==> java.util.Optional.orElse(T)
+  Line 135) wrappedNode.getTypeArguments().map(nodes -> ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>())) ==> java.util.Optional.map(java.util.function.Function<? super T, ? extends U>)
+  Line 135) wrappedNode.getTypeArguments() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getTypeArguments()
+  Line 138) ((NodeWithTypeArguments<?>) nodes).getTypeArguments().orElse(new NodeList<>()) ==> java.util.Optional.orElse(T)
+  Line 138) ((NodeWithTypeArguments<?>) nodes).getTypeArguments() ==> com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments.getTypeArguments()
+  Line 142) type.toString().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 142) type.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 145) SymbolReference.solved(new JavaParserTypeParameter(new TypeParameter(matchingType.toString()), typeSolver)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 146) matchingType.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 149) typeArgumentsMatch.isPresent() ==> java.util.Optional.isPresent()
+  Line 150) typeArgumentsMatch.get() ==> java.util.Optional.get()
+  Line 154) myDeclaration.getAncestors() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getAncestors()
+  Line 156) ancestor.getTypeDeclaration().getName().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 156) ancestor.getTypeDeclaration().getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
+  Line 156) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 157) SymbolReference.solved(ancestor.getTypeDeclaration()) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 157) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 161) ancestor.getTypeDeclaration().internalTypes() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.internalTypes()
+  Line 161) ancestor.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 162) internalTypeDeclaration.getName().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 162) internalTypeDeclaration.getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
+  Line 163) SymbolReference.solved(internalTypeDeclaration) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 171) getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 171) getParent() ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.AbstractJavaParserContext.getParent()
+  Line 177) Preconditions.checkArgument(typeSolver != null) ==> com.google.common.base.Preconditions.checkArgument(boolean)
+  Line 179) myDeclaration.hasVisibleField(name) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.hasVisibleField(java.lang.String)
+  Line 180) SymbolReference.solved(myDeclaration.getVisibleField(name)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 180) myDeclaration.getVisibleField(name) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getVisibleField(java.lang.String)
+  Line 183) getParent().solveSymbol(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveSymbol(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 183) getParent() ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.AbstractJavaParserContext.getParent()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CatchClauseContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CatchClauseContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CatchClauseContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CatchClauseContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ClassOrInterfaceDeclarationContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ClassOrInterfaceDeclarationContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ClassOrInterfaceDeclarationContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ClassOrInterfaceDeclarationContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CompilationUnitContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CompilationUnitContext.txt
new file mode 100644
index 0000000..f2531ec
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_CompilationUnitContext.txt
@@ -0,0 +1,130 @@
+  Line 49) name.contains(".") ==> java.lang.String.contains(java.lang.CharSequence)
+  Line 69) itName.contains(".") ==> java.lang.String.contains(java.lang.CharSequence)
+  Line 70) getType(itName) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getType(java.lang.String)
+  Line 71) getMember(itName) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getMember(java.lang.String)
+  Line 72) this.solveType(typeName, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 73) type.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 74) new SymbolSolver(typeSolver).solveSymbolInType(type.getCorrespondingDeclaration(), memberName) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String)
+  Line 74) type.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 81) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
+  Line 82) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
+  Line 83) importDecl.isStatic() ==> com.github.javaparser.ast.ImportDeclaration.isStatic()
+  Line 84) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
+  Line 85) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
+  Line 86) typeSolver.solveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
+  Line 87) new SymbolSolver(typeSolver).solveSymbolInType(importedType, name) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String)
+  Line 88) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 92) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
+  Line 95) getMember(whole) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getMember(java.lang.String)
+  Line 96) getType(whole) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getType(java.lang.String)
+  Line 98) memberName.equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 99) typeSolver.solveType(typeName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
+  Line 100) new SymbolSolver(typeSolver).solveSymbolInType(importedType, memberName) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveSymbolInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String)
+  Line 107) SymbolReference.unsolved(ValueDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 112) wrappedNode.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
+  Line 113) wrappedNode.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
+  Line 114) type.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 114) type.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 114) type.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 116) SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration) type)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 116) JavaParserFacade.get(typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration) type) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+  Line 116) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 118) SymbolReference.solved(new JavaParserAnnotationDeclaration((AnnotationDeclaration) type, typeSolver)) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 120) type.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 120) type.getClass() ==> java.lang.Object.getClass()
+  Line 126) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
+  Line 127) name.indexOf('.') ==> java.lang.String.indexOf(int)
+  Line 130) name.substring(0, dotPos) ==> java.lang.String.substring(int, int)
+  Line 133) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
+  Line 134) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
+  Line 135) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
+  Line 136) importDecl.getName().getQualifier().isPresent() ==> java.util.Optional.isPresent()
+  Line 136) importDecl.getName().getQualifier() ==> com.github.javaparser.ast.expr.Name.getQualifier()
+  Line 136) importDecl.getName() ==> com.github.javaparser.ast.ImportDeclaration.getName()
+  Line 137) importDecl.getName().getIdentifier().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 137) importDecl.getName().getIdentifier() ==> com.github.javaparser.ast.expr.Name.getIdentifier()
+  Line 137) importDecl.getName() ==> com.github.javaparser.ast.ImportDeclaration.getName()
+  Line 140) qName.endsWith("." + prefix) ==> java.lang.String.endsWith(java.lang.String)
+  Line 142) name.substring(dotPos) ==> java.lang.String.substring(int)
+  Line 147) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 148) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 149) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
+  Line 155) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
+  Line 156) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
+  Line 157) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
+  Line 158) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 159) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 160) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
+  Line 167) this.wrappedNode.getPackageDeclaration().isPresent() ==> java.util.Optional.isPresent()
+  Line 167) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
+  Line 168) this.wrappedNode.getPackageDeclaration().get().getName().toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 168) this.wrappedNode.getPackageDeclaration().get().getName() ==> com.github.javaparser.ast.PackageDeclaration.getName()
+  Line 168) this.wrappedNode.getPackageDeclaration().get() ==> java.util.Optional.get()
+  Line 168) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
+  Line 169) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 170) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 171) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
+  Line 176) typeSolver.tryToSolveType(qName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 177) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 178) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
+  Line 183) typeSolver.tryToSolveType("java.lang." + name) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 184) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 185) SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
+  Line 189) isQualifiedName(name) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.isQualifiedName(java.lang.String)
+  Line 190) SymbolReference.adapt(typeSolver.tryToSolveType(name), com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.adapt(com.github.javaparser.symbolsolver.model.resolution.SymbolReference<? extends O>, java.lang.Class<O>)
+  Line 190) typeSolver.tryToSolveType(name) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 192) SymbolReference.unsolved(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 197) type.getScope().isPresent() ==> java.util.Optional.isPresent()
+  Line 197) type.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 198) qName(type.getScope().get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.qName(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 198) type.getScope().get() ==> java.util.Optional.get()
+  Line 198) type.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 198) type.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 198) type.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 200) type.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 200) type.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 205) name.getQualifier().isPresent() ==> java.util.Optional.isPresent()
+  Line 205) name.getQualifier() ==> com.github.javaparser.ast.expr.Name.getQualifier()
+  Line 206) qName(name.getQualifier().get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.qName(com.github.javaparser.ast.expr.Name)
+  Line 206) name.getQualifier().get() ==> java.util.Optional.get()
+  Line 206) name.getQualifier() ==> com.github.javaparser.ast.expr.Name.getQualifier()
+  Line 206) name.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 208) name.getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 213) qName.split("\\.") ==> java.lang.String.split(java.lang.String)
+  Line 218) qName.lastIndexOf('.') ==> java.lang.String.lastIndexOf(int)
+  Line 222) qName.substring(0, lastDot) ==> java.lang.String.substring(int, int)
+  Line 228) wrappedNode.getImports() ==> com.github.javaparser.ast.CompilationUnit.getImports()
+  Line 229) importDecl.isStatic() ==> com.github.javaparser.ast.ImportDeclaration.isStatic()
+  Line 230) importDecl.isAsterisk() ==> com.github.javaparser.ast.ImportDeclaration.isAsterisk()
+  Line 231) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
+  Line 233) this.wrappedNode.getPackageDeclaration().isPresent() ==> java.util.Optional.isPresent()
+  Line 233) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
+  Line 234) this.wrappedNode.getPackageDeclaration().get().getName().getIdentifier().equals(packageName(importString)) ==> java.lang.String.equals(java.lang.Object)
+  Line 234) this.wrappedNode.getPackageDeclaration().get().getName().getIdentifier() ==> com.github.javaparser.ast.expr.Name.getIdentifier()
+  Line 234) this.wrappedNode.getPackageDeclaration().get().getName() ==> com.github.javaparser.ast.PackageDeclaration.getName()
+  Line 234) this.wrappedNode.getPackageDeclaration().get() ==> java.util.Optional.get()
+  Line 234) this.wrappedNode.getPackageDeclaration() ==> com.github.javaparser.ast.CompilationUnit.getPackageDeclaration()
+  Line 234) packageName(importString) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.packageName(java.lang.String)
+  Line 235) this.wrappedNode.getTypes().stream().anyMatch(it -> it.getName().getIdentifier().equals(toSimpleName(importString))) ==> java.util.stream.Stream.anyMatch(java.util.function.Predicate<? super T>)
+  Line 235) this.wrappedNode.getTypes().stream() ==> java.util.Collection.stream()
+  Line 235) this.wrappedNode.getTypes() ==> com.github.javaparser.ast.CompilationUnit.getTypes()
+  Line 235) it.getName().getIdentifier().equals(toSimpleName(importString)) ==> java.lang.String.equals(java.lang.Object)
+  Line 235) it.getName().getIdentifier() ==> com.github.javaparser.ast.expr.SimpleName.getIdentifier()
+  Line 235) it.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 235) toSimpleName(importString) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.toSimpleName(java.lang.String)
+  Line 238) SymbolReference.unsolved(MethodDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 241) typeSolver.solveType(importString) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
+  Line 242) MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 244) method.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 248) importDecl.getNameAsString() ==> com.github.javaparser.ast.nodeTypes.NodeWithName.getNameAsString()
+  Line 250) qName.equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 250) qName.endsWith("." + name) ==> java.lang.String.endsWith(java.lang.String)
+  Line 251) getType(qName) ==> com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext.getType(java.lang.String)
+  Line 252) typeSolver.solveType(typeName) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
+  Line 253) MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver) ==> com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic.solveMethodInType(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration, java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 254) method.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 261) SymbolReference.unsolved(MethodDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
+  Line 269) qName.lastIndexOf('.') ==> java.lang.String.lastIndexOf(int)
+  Line 273) qName.substring(0, index) ==> java.lang.String.substring(int, int)
+  Line 278) qName.lastIndexOf('.') ==> java.lang.String.lastIndexOf(int)
+  Line 282) qName.substring(index + 1) ==> java.lang.String.substring(int)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ConstructorContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ConstructorContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ConstructorContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ConstructorContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ContextHelper.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ContextHelper.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ContextHelper.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ContextHelper.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_EnumDeclarationContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_EnumDeclarationContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_EnumDeclarationContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_EnumDeclarationContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_FieldAccessContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_FieldAccessContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_FieldAccessContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_FieldAccessContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForStatementContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForStatementContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForStatementContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForStatementContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForechStatementContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForechStatementContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForechStatementContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_ForechStatementContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_JavaParserTypeDeclarationAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_JavaParserTypeDeclarationAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_JavaParserTypeDeclarationAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_JavaParserTypeDeclarationAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_LambdaExprContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_LambdaExprContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_LambdaExprContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_LambdaExprContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodCallExprContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodCallExprContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodCallExprContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodCallExprContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_MethodContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_StatementContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_StatementContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_StatementContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_StatementContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_SwitchEntryContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_SwitchEntryContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_SwitchEntryContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_SwitchEntryContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_TryWithResourceContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_TryWithResourceContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_TryWithResourceContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_contexts_TryWithResourceContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_DefaultConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_DefaultConstructorDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_DefaultConstructorDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_DefaultConstructorDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_Helper.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_Helper.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_Helper.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_Helper.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnnotationDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnnotationDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnnotationDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnnotationDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnonymousClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnonymousClassDeclaration.txt
new file mode 100644
index 0000000..d044fbc
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserAnonymousClassDeclaration.txt
@@ -0,0 +1,87 @@
+  Line 37) UUID.randomUUID() ==> java.util.UUID.randomUUID()
+  Line 44) JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver).solveType(wrappedNode.getType().getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 44) JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver).solveType(wrappedNode.getType().getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 44) JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 44) wrappedNode.getParentNode().get() ==> java.util.Optional.get()
+  Line 44) wrappedNode.getParentNode() ==> com.github.javaparser.ast.Node.getParentNode()
+  Line 45) wrappedNode.getType().getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 45) wrappedNode.getType().getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 45) wrappedNode.getType() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getType()
+  Line 54) wrappedNode.getAnonymousClassBody().get().stream().filter(node -> memberClass.isAssignableFrom(node.getClass())).map(node -> (T) node).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 54) wrappedNode.getAnonymousClassBody().get().stream().filter(node -> memberClass.isAssignableFrom(node.getClass())).map(node -> (T) node) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 54) wrappedNode.getAnonymousClassBody().get().stream().filter(node -> memberClass.isAssignableFrom(node.getClass())) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 54) wrappedNode.getAnonymousClassBody().get().stream() ==> java.util.Collection.stream()
+  Line 54) wrappedNode.getAnonymousClassBody().get() ==> java.util.Optional.get()
+  Line 54) wrappedNode.getAnonymousClassBody() ==> com.github.javaparser.ast.expr.ObjectCreationExpr.getAnonymousClassBody()
+  Line 58) memberClass.isAssignableFrom(node.getClass()) ==> java.lang.Class.isAssignableFrom(java.lang.Class<? extends java.lang.Object>)
+  Line 58) node.getClass() ==> java.lang.Object.getClass()
+  Line 60) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 65) typeSolver.solveType(Object.class.getCanonicalName()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
+  Line 65) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 70) superTypeDeclaration.asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 76) superTypeDeclaration.asReferenceType().getAncestors().stream().filter(type -> type.getTypeDeclaration().isInterface()).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 76) superTypeDeclaration.asReferenceType().getAncestors().stream().filter(type -> type.getTypeDeclaration().isInterface()) ==> java.util.stream.Stream.filter(java.util.function.Predicate<? super T>)
+  Line 76) superTypeDeclaration.asReferenceType().getAncestors().stream() ==> java.util.Collection.stream()
+  Line 76) superTypeDeclaration.asReferenceType().getAncestors() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAncestors()
+  Line 76) superTypeDeclaration.asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 79) type.getTypeDeclaration().isInterface() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isInterface()
+  Line 79) type.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 80) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class).stream().map(ctor -> new JavaParserConstructorDeclaration(this, ctor, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class).stream().map(ctor -> new JavaParserConstructorDeclaration(this, ctor, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class).stream() ==> java.util.Collection.stream()
+  Line 86) findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
+  Line 89) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 100) ImmutableList.<ReferenceType>builder().add(getSuperClass()).addAll(superTypeDeclaration.asReferenceType().getAncestors()).build() ==> com.google.common.collect.ImmutableList.Builder.build()
+  Line 100) ImmutableList.<ReferenceType>builder().add(getSuperClass()).addAll(superTypeDeclaration.asReferenceType().getAncestors()) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
+  Line 100) ImmutableList.<ReferenceType>builder().add(getSuperClass()) ==> com.google.common.collect.ImmutableList.Builder.add(E)
+  Line 100) ImmutableList.<ReferenceType>builder() ==> com.google.common.collect.ImmutableList.builder()
+  Line 102) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getSuperClass()
+  Line 103) superTypeDeclaration.asReferenceType().getAncestors() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAncestors()
+  Line 103) superTypeDeclaration.asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class).stream().flatMap(field -> field.getVariables().stream().map(variable -> new JavaParserFieldDeclaration(variable, typeSolver))).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class).stream().flatMap(field -> field.getVariables().stream().map(variable -> new JavaParserFieldDeclaration(variable, typeSolver))) ==> java.util.stream.Stream.flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>)
+  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class).stream() ==> java.util.Collection.stream()
+  Line 111) findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
+  Line 114) field.getVariables().stream().map(variable -> new JavaParserFieldDeclaration(variable, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 114) field.getVariables().stream() ==> java.util.Collection.stream()
+  Line 114) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
+  Line 117) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 120) getSuperClass().getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
+  Line 120) getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 120) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getSuperClass()
+  Line 123) getInterfaces().stream().flatMap(inteface -> inteface.getTypeDeclaration().getAllFields().stream()).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 123) getInterfaces().stream().flatMap(inteface -> inteface.getTypeDeclaration().getAllFields().stream()) ==> java.util.stream.Stream.flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>)
+  Line 123) getInterfaces().stream() ==> java.util.Collection.stream()
+  Line 123) getInterfaces() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getInterfaces()
+  Line 124) inteface.getTypeDeclaration().getAllFields().stream() ==> java.util.Collection.stream()
+  Line 124) inteface.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
+  Line 124) inteface.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 125) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields).addAll(superClassFields).addAll(interfaceFields).build() ==> com.google.common.collect.ImmutableList.Builder.build()
+  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields).addAll(superClassFields).addAll(interfaceFields) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
+  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields).addAll(superClassFields) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
+  Line 128) ImmutableList.<FieldDeclaration>builder().addAll(myFields) ==> com.google.common.collect.ImmutableList.Builder.addAll(java.lang.Iterable<? extends E>)
+  Line 128) ImmutableList.<FieldDeclaration>builder() ==> com.google.common.collect.ImmutableList.builder()
+  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class).stream().map(method -> new JavaParserMethodDeclaration(method, typeSolver)).collect(Collectors.toSet()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class).stream().map(method -> new JavaParserMethodDeclaration(method, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class).stream() ==> java.util.Collection.stream()
+  Line 139) findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
+  Line 142) Collectors.toSet() ==> java.util.stream.Collectors.toSet()
+  Line 162) Helper.getPackageName(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.getPackageName(com.github.javaparser.ast.Node)
+  Line 167) Helper.getClassName("", wrappedNode) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.getClassName(java.lang.String, com.github.javaparser.ast.Node)
+  Line 172) Helper.containerName(getParentNode(wrappedNode)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.containerName(com.github.javaparser.ast.Node)
+  Line 172) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 173) containerName.isEmpty() ==> java.lang.String.isEmpty()
+  Line 174) getName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getName()
+  Line 176) getName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.getName()
+  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class).stream().map(typeMember -> JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember)).collect(Collectors.toSet()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class).stream().map(typeMember -> JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class).stream() ==> java.util.Collection.stream()
+  Line 183) findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration.findMembersOfKind(java.lang.Class<T>)
+  Line 185) JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
+  Line 185) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 186) Collectors.toSet() ==> java.util.stream.Collectors.toSet()
+  Line 196) Lists.newArrayList() ==> com.google.common.collect.Lists.newArrayList()
+  Line 201) this.getClass().getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 201) this.getClass() ==> java.lang.Object.getClass()
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt
new file mode 100644
index 0000000..6b42d18
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt
@@ -0,0 +1,139 @@
+  Line 64) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
+  Line 79) getClass() ==> java.lang.Object.getClass()
+  Line 79) o.getClass() ==> java.lang.Object.getClass()
+  Line 83) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
+  Line 90) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
+  Line 107) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 110) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
+  Line 111) fields.add(new JavaParserFieldDeclaration(vd, typeSolver)) ==> java.util.ArrayList.add(E)
+  Line 116) this.getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 116) this.getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
+  Line 118) fields.addAll(superclass.getAllFields()) ==> java.util.ArrayList.addAll(java.util.Collection<? extends E>)
+  Line 118) superclass.getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
+  Line 120) getInterfaces().forEach(interf -> interf.getTypeDeclaration().getAllFields().forEach(f -> {
+    fields.add(f);
+})) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
+  Line 120) getInterfaces() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getInterfaces()
+  Line 120) interf.getTypeDeclaration().getAllFields().forEach(f -> {
+    fields.add(f);
+}) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
+  Line 120) interf.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
+  Line 120) interf.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 121) fields.add(f) ==> java.util.ArrayList.add(E)
+  Line 132) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
+  Line 133) ctx.solveMethod(name, parameterTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 138) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 147) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 147) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 152) wrappedNode.getExtendedTypes().isEmpty() ==> com.github.javaparser.ast.NodeList.isEmpty()
+  Line 152) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 153) object() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.object()
+  Line 155) toReferenceType(wrappedNode.getExtendedTypes().get(0)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 155) wrappedNode.getExtendedTypes().get(0) ==> com.github.javaparser.ast.NodeList.get(int)
+  Line 155) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 162) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 163) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 164) interfaces.add(toReferenceType(t)) ==> java.util.List.add(E)
+  Line 164) toReferenceType(t) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 173) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 176) declared.add(new JavaParserConstructorDeclaration(this, constructorDeclaration, typeSolver)) ==> java.util.List.add(E)
+  Line 179) declared.isEmpty() ==> java.util.List.isEmpty()
+  Line 181) ImmutableList.of(new DefaultConstructorDeclaration(this)) ==> com.google.common.collect.ImmutableList.of(E)
+  Line 189) wrappedNode.getAnnotations() ==> com.github.javaparser.ast.body.BodyDeclaration.getAnnotations()
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName) ==> java.lang.String.equals(java.lang.Object)
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 190) annotationExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 190) annotationExpr.getName() ==> com.github.javaparser.ast.expr.AnnotationExpr.getName()
+  Line 199) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
+  Line 204) javaParserTypeAdapter.getPackageName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getPackageName()
+  Line 209) javaParserTypeAdapter.getClassName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getClassName()
+  Line 214) javaParserTypeAdapter.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getQualifiedName()
+  Line 219) javaParserTypeAdapter.isAssignableBy(other) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 224) javaParserTypeAdapter.isAssignableBy(type) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 230) this.getQualifiedName().equals(other.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
+  Line 230) this.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getQualifiedName()
+  Line 230) other.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 233) getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 233) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
+  Line 236) Object.class.getCanonicalName().equals(superclass.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
+  Line 236) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 236) superclass.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 239) superclass.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 244) this.wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 245) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 246) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
+  Line 247) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 263) this.wrappedNode.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 263) this.wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 263) this.wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 264) SymbolReference.solved(this) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 266) javaParserTypeAdapter.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 267) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 271) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 272) name.startsWith(prefix) ==> java.lang.String.startsWith(java.lang.String)
+  Line 272) name.length() ==> java.lang.String.length()
+  Line 272) prefix.length() ==> java.lang.String.length()
+  Line 273) new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 273) name.substring(prefix.length()) ==> java.lang.String.substring(int)
+  Line 273) prefix.length() ==> java.lang.String.length()
+  Line 276) getContext().getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 276) getContext().getParent() ==> com.github.javaparser.symbolsolver.core.resolution.Context.getParent()
+  Line 276) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
+  Line 282) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
+  Line 284) ancestors.add(superclass) ==> java.util.List.add(E)
+  Line 286) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 287) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 288) toReferenceType(implemented) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 289) ancestors.add(ancestor) ==> java.util.List.add(E)
+  Line 298) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 300) methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)) ==> java.util.Set.add(E)
+  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 308) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
+  Line 308) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
+  Line 310) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 324) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
+  Line 324) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.TypeDeclaration.getModifiers()
+  Line 333) typeSolver.solveType(Object.class.getCanonicalName()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
+  Line 333) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 339) this.wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 341) res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member)) ==> java.util.Set.add(E)
+  Line 341) JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
+  Line 341) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 349) javaParserTypeAdapter.containerType() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.containerType()
+  Line 357) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 357) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 358) classOrInterfaceType.getScope().isPresent() ==> java.util.Optional.isPresent()
+  Line 358) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 360) classOrInterfaceType.getScope().get().toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 360) classOrInterfaceType.getScope().get() ==> java.util.Optional.get()
+  Line 360) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 362) solveType(className, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 363) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 364) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 365) localScope.isPresent() ==> java.util.Optional.isPresent()
+  Line 366) localScope.get().getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 366) localScope.get().getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 366) localScope.get() ==> java.util.Optional.get()
+  Line 366) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 366) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 367) solveType(localName, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 370) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 371) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 371) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 373) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
+  Line 373) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 374) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 374) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 376) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
+  Line 376) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
+  Line 376) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 377) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 377) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 378) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 379) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 379) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration_J9.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration_J9.txt
new file mode 100644
index 0000000..6b42d18
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration_J9.txt
@@ -0,0 +1,139 @@
+  Line 64) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
+  Line 79) getClass() ==> java.lang.Object.getClass()
+  Line 79) o.getClass() ==> java.lang.Object.getClass()
+  Line 83) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
+  Line 90) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
+  Line 107) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 110) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
+  Line 111) fields.add(new JavaParserFieldDeclaration(vd, typeSolver)) ==> java.util.ArrayList.add(E)
+  Line 116) this.getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 116) this.getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
+  Line 118) fields.addAll(superclass.getAllFields()) ==> java.util.ArrayList.addAll(java.util.Collection<? extends E>)
+  Line 118) superclass.getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
+  Line 120) getInterfaces().forEach(interf -> interf.getTypeDeclaration().getAllFields().forEach(f -> {
+    fields.add(f);
+})) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
+  Line 120) getInterfaces() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getInterfaces()
+  Line 120) interf.getTypeDeclaration().getAllFields().forEach(f -> {
+    fields.add(f);
+}) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
+  Line 120) interf.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
+  Line 120) interf.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 121) fields.add(f) ==> java.util.ArrayList.add(E)
+  Line 132) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
+  Line 133) ctx.solveMethod(name, parameterTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 138) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 147) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 147) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 152) wrappedNode.getExtendedTypes().isEmpty() ==> com.github.javaparser.ast.NodeList.isEmpty()
+  Line 152) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 153) object() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.object()
+  Line 155) toReferenceType(wrappedNode.getExtendedTypes().get(0)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 155) wrappedNode.getExtendedTypes().get(0) ==> com.github.javaparser.ast.NodeList.get(int)
+  Line 155) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 162) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 163) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 164) interfaces.add(toReferenceType(t)) ==> java.util.List.add(E)
+  Line 164) toReferenceType(t) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 173) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 176) declared.add(new JavaParserConstructorDeclaration(this, constructorDeclaration, typeSolver)) ==> java.util.List.add(E)
+  Line 179) declared.isEmpty() ==> java.util.List.isEmpty()
+  Line 181) ImmutableList.of(new DefaultConstructorDeclaration(this)) ==> com.google.common.collect.ImmutableList.of(E)
+  Line 189) wrappedNode.getAnnotations() ==> com.github.javaparser.ast.body.BodyDeclaration.getAnnotations()
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName) ==> java.lang.String.equals(java.lang.Object)
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 190) solveType(annotationExpr.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 190) annotationExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 190) annotationExpr.getName() ==> com.github.javaparser.ast.expr.AnnotationExpr.getName()
+  Line 199) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
+  Line 204) javaParserTypeAdapter.getPackageName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getPackageName()
+  Line 209) javaParserTypeAdapter.getClassName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getClassName()
+  Line 214) javaParserTypeAdapter.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getQualifiedName()
+  Line 219) javaParserTypeAdapter.isAssignableBy(other) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 224) javaParserTypeAdapter.isAssignableBy(type) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 230) this.getQualifiedName().equals(other.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
+  Line 230) this.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getQualifiedName()
+  Line 230) other.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 233) getSuperClass().getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 233) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
+  Line 236) Object.class.getCanonicalName().equals(superclass.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
+  Line 236) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 236) superclass.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 239) superclass.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 244) this.wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 245) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 246) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
+  Line 247) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 263) this.wrappedNode.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 263) this.wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 263) this.wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 264) SymbolReference.solved(this) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 266) javaParserTypeAdapter.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 267) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 271) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 272) name.startsWith(prefix) ==> java.lang.String.startsWith(java.lang.String)
+  Line 272) name.length() ==> java.lang.String.length()
+  Line 272) prefix.length() ==> java.lang.String.length()
+  Line 273) new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 273) name.substring(prefix.length()) ==> java.lang.String.substring(int)
+  Line 273) prefix.length() ==> java.lang.String.length()
+  Line 276) getContext().getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 276) getContext().getParent() ==> com.github.javaparser.symbolsolver.core.resolution.Context.getParent()
+  Line 276) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getContext()
+  Line 282) getSuperClass() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.getSuperClass()
+  Line 284) ancestors.add(superclass) ==> java.util.List.add(E)
+  Line 286) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 287) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 288) toReferenceType(implemented) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 289) ancestors.add(ancestor) ==> java.util.List.add(E)
+  Line 298) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 300) methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)) ==> java.util.Set.add(E)
+  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 308) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
+  Line 308) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
+  Line 310) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 324) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
+  Line 324) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.TypeDeclaration.getModifiers()
+  Line 333) typeSolver.solveType(Object.class.getCanonicalName()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.solveType(java.lang.String)
+  Line 333) Object.class.getCanonicalName() ==> java.lang.Class.getCanonicalName()
+  Line 339) this.wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 341) res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member)) ==> java.util.Set.add(E)
+  Line 341) JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
+  Line 341) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 349) javaParserTypeAdapter.containerType() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.containerType()
+  Line 357) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 357) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 358) classOrInterfaceType.getScope().isPresent() ==> java.util.Optional.isPresent()
+  Line 358) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 360) classOrInterfaceType.getScope().get().toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 360) classOrInterfaceType.getScope().get() ==> java.util.Optional.get()
+  Line 360) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 362) solveType(className, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 363) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 364) classOrInterfaceType.getScope() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getScope()
+  Line 365) localScope.isPresent() ==> java.util.Optional.isPresent()
+  Line 366) localScope.get().getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 366) localScope.get().getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 366) localScope.get() ==> java.util.Optional.get()
+  Line 366) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 366) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 367) solveType(localName, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 370) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 371) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 371) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 373) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
+  Line 373) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 374) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 374) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 376) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
+  Line 376) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
+  Line 376) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 377) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 377) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 378) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 379) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 379) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserConstructorDeclaration.txt
new file mode 100644
index 0000000..e012479
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserConstructorDeclaration.txt
@@ -0,0 +1,15 @@
+  Line 48) this.wrappedNode.getParameters().size() ==> com.github.javaparser.ast.NodeList.size()
+  Line 48) this.wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
+  Line 53) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserConstructorDeclaration.getNumberOfParams()
+  Line 54) String.format("No param with index %d. Number of params: %d", i, getNumberOfParams()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
+  Line 54) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserConstructorDeclaration.getNumberOfParams()
+  Line 56) wrappedNode.getParameters().get(i) ==> com.github.javaparser.ast.NodeList.get(int)
+  Line 56) wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
+  Line 61) this.classDeclaration.getName() ==> com.github.javaparser.symbolsolver.model.declarations.Declaration.getName()
+  Line 75) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
+  Line 75) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.CallableDeclaration.getModifiers()
+  Line 80) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 80) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 80) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
+  Line 80) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getTypeParameters()
+  Line 80) Collectors.toList() ==> java.util.stream.Collectors.toList()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumConstantDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumConstantDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumConstantDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumConstantDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserEnumDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserFieldDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserFieldDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserFieldDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserFieldDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserInterfaceDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserInterfaceDeclaration.txt
new file mode 100644
index 0000000..baa299b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserInterfaceDeclaration.txt
@@ -0,0 +1,120 @@
+  Line 52) wrappedNode.isInterface() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.isInterface()
+  Line 63) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 65) methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)) ==> java.util.Set.add(E)
+  Line 72) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 82) getClass() ==> java.lang.Object.getClass()
+  Line 82) o.getClass() ==> java.lang.Object.getClass()
+  Line 86) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
+  Line 93) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
+  Line 98) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 98) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 108) wrappedNode.getAnnotations() ==> com.github.javaparser.ast.body.BodyDeclaration.getAnnotations()
+  Line 109) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName) ==> java.lang.String.equals(java.lang.Object)
+  Line 109) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 109) solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 109) solveType(annotationExpr.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 109) annotationExpr.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 109) annotationExpr.getName() ==> com.github.javaparser.ast.expr.AnnotationExpr.getName()
+  Line 124) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 125) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 126) interfaces.add(new ReferenceTypeImpl(solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration().asInterface(), typeSolver)) ==> java.util.List.add(E)
+  Line 126) solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration().asInterface() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asInterface()
+  Line 126) solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 126) solveType(t.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 126) t.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 126) t.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 134) javaParserTypeAdapter.getPackageName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getPackageName()
+  Line 139) javaParserTypeAdapter.getClassName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getClassName()
+  Line 144) javaParserTypeAdapter.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.getQualifiedName()
+  Line 149) javaParserTypeAdapter.isAssignableBy(other) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 154) javaParserTypeAdapter.isAssignableBy(type) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 160) this.getQualifiedName().equals(other.getQualifiedName()) ==> java.lang.String.equals(java.lang.Object)
+  Line 160) this.getQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.getQualifiedName()
+  Line 160) other.getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 163) this.wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 164) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 165) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
+  Line 166) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 172) this.wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 173) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 174) new SymbolSolver(typeSolver).solveType(type) ==> com.github.javaparser.symbolsolver.resolution.SymbolSolver.solveType(com.github.javaparser.ast.type.Type)
+  Line 175) ancestor.canBeAssignedTo(other) ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.canBeAssignedTo(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)
+  Line 192) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 195) field.getVariables() ==> com.github.javaparser.ast.body.FieldDeclaration.getVariables()
+  Line 196) fields.add(new JavaParserFieldDeclaration(vd, typeSolver)) ==> java.util.ArrayList.add(E)
+  Line 201) getAncestors().forEach(a -> {
+    if (a.getTypeDeclaration() != this) {
+        fields.addAll(a.getTypeDeclaration().getAllFields());
+    }
+}) ==> java.lang.Iterable.forEach(java.util.function.Consumer<? super T>)
+  Line 201) getAncestors() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.getAncestors()
+  Line 202) a.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 203) fields.addAll(a.getTypeDeclaration().getAllFields()) ==> java.util.ArrayList.addAll(java.util.Collection<? extends E>)
+  Line 203) a.getTypeDeclaration().getAllFields() ==> com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.getAllFields()
+  Line 203) a.getTypeDeclaration() ==> com.github.javaparser.symbolsolver.model.typesystem.ReferenceType.getTypeDeclaration()
+  Line 220) this.wrappedNode.getName().getId().equals(name) ==> java.lang.String.equals(java.lang.Object)
+  Line 220) this.wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 220) this.wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 221) SymbolReference.solved(this) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.solved(S2)
+  Line 223) javaParserTypeAdapter.solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 224) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 228) wrappedNode.getName() ==> com.github.javaparser.ast.body.TypeDeclaration.getName()
+  Line 229) name.startsWith(prefix) ==> java.lang.String.startsWith(java.lang.String)
+  Line 229) name.length() ==> java.lang.String.length()
+  Line 229) prefix.length() ==> java.lang.String.length()
+  Line 230) new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 230) name.substring(prefix.length()) ==> java.lang.String.substring(int)
+  Line 230) prefix.length() ==> java.lang.String.length()
+  Line 233) getContext().getParent().solveType(name, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 233) getContext().getParent() ==> com.github.javaparser.symbolsolver.core.resolution.Context.getParent()
+  Line 233) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.getContext()
+  Line 239) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 240) wrappedNode.getExtendedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getExtendedTypes()
+  Line 241) ancestors.add(toReferenceType(extended)) ==> java.util.List.add(E)
+  Line 241) toReferenceType(extended) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 244) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 245) wrappedNode.getImplementedTypes() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getImplementedTypes()
+  Line 246) ancestors.add(toReferenceType(implemented)) ==> java.util.List.add(E)
+  Line 246) toReferenceType(implemented) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.toReferenceType(com.github.javaparser.ast.type.ClassOrInterfaceType)
+  Line 254) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
+  Line 255) Collections.emptyList() ==> java.util.Collections.emptyList()
+  Line 257) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 257) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 257) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
+  Line 257) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters()
+  Line 259) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 274) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
+  Line 274) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.TypeDeclaration.getModifiers()
+  Line 280) this.wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers()
+  Line 282) res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member)) ==> java.util.Set.add(E)
+  Line 282) JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration) member) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?>)
+  Line 282) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 290) javaParserTypeAdapter.containerType() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeAdapter.containerType()
+  Line 299) classOrInterfaceType.toString().indexOf('.') ==> java.lang.String.indexOf(int)
+  Line 299) classOrInterfaceType.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 300) typeSolver.tryToSolveType(classOrInterfaceType.toString()) ==> com.github.javaparser.symbolsolver.model.resolution.TypeSolver.tryToSolveType(java.lang.String)
+  Line 300) classOrInterfaceType.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 302) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 303) solveType(classOrInterfaceType.toString(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 303) classOrInterfaceType.toString() ==> com.github.javaparser.ast.Node.toString()
+  Line 305) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 306) solveType(classOrInterfaceType.getName().getId(), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration.solveType(java.lang.String, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 306) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 306) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 308) ref.isSolved() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.isSolved()
+  Line 309) classOrInterfaceType.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 309) classOrInterfaceType.getName() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getName()
+  Line 311) classOrInterfaceType.getTypeArguments().isPresent() ==> java.util.Optional.isPresent()
+  Line 311) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 312) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 312) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
+  Line 314) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 314) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 314) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream()
+  Line 314) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get()
+  Line 314) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments()
+  Line 315) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 315) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 316) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 317) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()
+  Line 317) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration()
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserMethodDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserMethodDeclaration.txt
new file mode 100644
index 0000000..9540661
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserMethodDeclaration.txt
@@ -0,0 +1,30 @@
+  Line 58) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 59) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 62) JavaParserFactory.toTypeDeclaration(getParentNode(wrappedNode), typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.toTypeDeclaration(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 62) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 68) JavaParserFacade.get(typeSolver).convert(wrappedNode.getType(), getContext()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.symbolsolver.core.resolution.Context)
+  Line 68) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 68) wrappedNode.getType() ==> com.github.javaparser.ast.body.MethodDeclaration.getType()
+  Line 68) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration.getContext()
+  Line 73) wrappedNode.getParameters().size() ==> com.github.javaparser.ast.NodeList.size()
+  Line 73) wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
+  Line 78) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration.getNumberOfParams()
+  Line 79) String.format("No param with index %d. Number of params: %d", i, getNumberOfParams()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
+  Line 79) getNumberOfParams() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration.getNumberOfParams()
+  Line 81) wrappedNode.getParameters().get(i) ==> com.github.javaparser.ast.NodeList.get(int)
+  Line 81) wrappedNode.getParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getParameters()
+  Line 89) new MethodDeclarationCommonLogic(this, typeSolver).resolveTypeVariables(context, parameterTypes) ==> com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic.resolveTypeVariables(com.github.javaparser.symbolsolver.core.resolution.Context, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>)
+  Line 93) JavaParserFactory.getContext(wrappedNode, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory.getContext(com.github.javaparser.ast.Node, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 98) wrappedNode.getBody().isPresent() ==> java.util.Optional.isPresent()
+  Line 98) wrappedNode.getBody() ==> com.github.javaparser.ast.body.MethodDeclaration.getBody()
+  Line 103) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 103) wrappedNode.getName() ==> com.github.javaparser.ast.body.CallableDeclaration.getName()
+  Line 123) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 123) this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 123) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream()
+  Line 123) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.CallableDeclaration.getTypeParameters()
+  Line 123) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 128) wrappedNode.isDefault() ==> com.github.javaparser.ast.body.MethodDeclaration.isDefault()
+  Line 133) wrappedNode.isStatic() ==> com.github.javaparser.ast.nodeTypes.modifiers.NodeWithStaticModifier.isStatic()
+  Line 147) Helper.toAccessLevel(wrappedNode.getModifiers()) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.Helper.toAccessLevel(java.util.EnumSet<com.github.javaparser.ast.Modifier>)
+  Line 147) wrappedNode.getModifiers() ==> com.github.javaparser.ast.body.CallableDeclaration.getModifiers()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserParameterDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserParameterDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserParameterDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserParameterDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserSymbolDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserSymbolDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserSymbolDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserSymbolDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeParameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeParameter.txt
new file mode 100644
index 0000000..e67d352
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeParameter.txt
@@ -0,0 +1,45 @@
+  Line 56) Collections.emptySet() ==> java.util.Collections.emptySet()
+  Line 60) getContext().solveMethod(name, parameterTypes, false, typeSolver) ==> com.github.javaparser.symbolsolver.core.resolution.Context.solveMethod(java.lang.String, java.util.List<com.github.javaparser.symbolsolver.model.typesystem.Type>, boolean, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 60) getContext() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContext()
+  Line 70) wrappedNode.equals(that.wrappedNode) ==> com.github.javaparser.ast.Node.equals(java.lang.Object)
+  Line 77) wrappedNode.hashCode() ==> com.github.javaparser.ast.Node.hashCode()
+  Line 78) typeSolver.hashCode() ==> java.lang.Object.hashCode()
+  Line 84) wrappedNode.getName().getId() ==> com.github.javaparser.ast.nodeTypes.NodeWithIdentifier.getId()
+  Line 84) wrappedNode.getName() ==> com.github.javaparser.ast.type.TypeParameter.getName()
+  Line 89) isAssignableBy(new ReferenceTypeImpl(other, typeSolver)) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.isAssignableBy(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 94) getContainer() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainer()
+  Line 96) ((ReferenceTypeDeclaration) container).getQualifiedName() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getQualifiedName()
+  Line 98) ((JavaParserConstructorDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
+  Line 100) ((JavaParserMethodDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
+  Line 106) getContainer() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainer()
+  Line 108) ((ReferenceTypeDeclaration) container).getId() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.getId()
+  Line 110) ((JavaParserConstructorDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
+  Line 112) ((JavaParserMethodDeclaration) container).getQualifiedSignature() ==> com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration.getQualifiedSignature()
+  Line 118) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 121) JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+  Line 121) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 124) jpConstructorDeclaration.getAncestorOfType(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class) ==> com.github.javaparser.HasParentNode.getAncestorOfType(java.lang.Class<N>)
+  Line 125) jpTypeDeclaration.isPresent() ==> java.util.Optional.isPresent()
+  Line 126) JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration.get()) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.getTypeDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+  Line 126) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 126) jpTypeDeclaration.get() ==> java.util.Optional.get()
+  Line 127) typeDeclaration.isClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.isClass()
+  Line 128) typeDeclaration.asClass() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asClass()
+  Line 140) String.format("%s.%s", getContainerQualifiedName(), getName()) ==> java.lang.String.format(java.lang.String, java.lang.Object...)
+  Line 140) getContainerQualifiedName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainerQualifiedName()
+  Line 140) getName() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getName()
+  Line 145) wrappedNode.getTypeBound().stream().map((astB) -> toBound(astB, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 145) wrappedNode.getTypeBound().stream().map((astB) -> toBound(astB, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 145) wrappedNode.getTypeBound().stream() ==> java.util.Collection.stream()
+  Line 145) wrappedNode.getTypeBound() ==> com.github.javaparser.ast.type.TypeParameter.getTypeBound()
+  Line 145) toBound(astB, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.toBound(com.github.javaparser.ast.type.ClassOrInterfaceType, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 145) Collectors.toList() ==> java.util.stream.Collectors.toList()
+  Line 149) JavaParserFacade.get(typeSolver).convertToUsage(classOrInterfaceType, classOrInterfaceType) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convertToUsage(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node)
+  Line 149) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 150) Bound.extendsBound(type) ==> com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration.Bound.extendsBound(com.github.javaparser.symbolsolver.model.typesystem.Type)
+  Line 199) Collections.emptyList() ==> java.util.Collections.emptyList()
+  Line 213) wrappedNode.getName() ==> com.github.javaparser.ast.type.TypeParameter.getName()
+  Line 213) wrappedNode.getTypeBound() ==> com.github.javaparser.ast.type.TypeParameter.getTypeBound()
+  Line 218) getContainer() ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter.getContainer()
+  Line 220) Optional.of((ReferenceTypeDeclaration) container) ==> java.util.Optional.of(T)
+  Line 222) Optional.empty() ==> java.util.Optional.empty()
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeVariableDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeVariableDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeVariableDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserTypeVariableDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_AbstractSymbolDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_AbstractSymbolDeclarator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_AbstractSymbolDeclarator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_AbstractSymbolDeclarator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_FieldSymbolDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_FieldSymbolDeclarator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_FieldSymbolDeclarator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_FieldSymbolDeclarator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_NoSymbolDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_NoSymbolDeclarator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_NoSymbolDeclarator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_NoSymbolDeclarator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_ParameterSymbolDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_ParameterSymbolDeclarator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_ParameterSymbolDeclarator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_ParameterSymbolDeclarator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_VariableSymbolDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_VariableSymbolDeclarator.txt
new file mode 100644
index 0000000..14ddbb6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarators_VariableSymbolDeclarator.txt
@@ -0,0 +1,7 @@
+  Line 38) getParentNode(wrappedNode) ==> com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode(com.github.javaparser.ast.Node)
+  Line 45) wrappedNode.getVariables().stream().map(v -> JavaParserSymbolDeclaration.localVar(v, typeSolver)).collect(Collectors.toCollection(() -> new LinkedList<>())) ==> java.util.stream.Stream.collect(java.util.stream.Collector<? super T, A, R>)
+  Line 45) wrappedNode.getVariables().stream().map(v -> JavaParserSymbolDeclaration.localVar(v, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
+  Line 45) wrappedNode.getVariables().stream() ==> java.util.Collection.stream()
+  Line 45) wrappedNode.getVariables() ==> com.github.javaparser.ast.expr.VariableDeclarationExpr.getVariables()
+  Line 46) JavaParserSymbolDeclaration.localVar(v, typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration.localVar(com.github.javaparser.ast.body.VariableDeclarator, com.github.javaparser.symbolsolver.model.resolution.TypeSolver)
+  Line 48) Collectors.toCollection(() -> new LinkedList<>()) ==> java.util.stream.Collectors.toCollection(java.util.function.Supplier<C>)
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistClassDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistClassDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistClassDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistConstructorDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistConstructorDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistConstructorDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistEnumDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistEnumDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistEnumDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistEnumDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFactory.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFactory.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFactory.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFactory.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFieldDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFieldDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFieldDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistFieldDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistInterfaceDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistInterfaceDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistInterfaceDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistInterfaceDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistMethodDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistMethodDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistMethodDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistMethodDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistParameterDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistParameterDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistParameterDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistParameterDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeDeclarationAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeDeclarationAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeDeclarationAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeDeclarationAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeParameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeParameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeParameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistTypeParameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistUtils.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistUtils.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistUtils.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javassistmodel_JavassistUtils.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_LazyType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_LazyType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_LazyType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_LazyType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_ReferenceTypeImpl.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_ReferenceTypeImpl.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_ReferenceTypeImpl.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_model_typesystem_ReferenceTypeImpl.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_MyObjectProvider.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_MyObjectProvider.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_MyObjectProvider.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_MyObjectProvider.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassAdapter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassAdapter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassAdapter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassAdapter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionClassDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionConstructorDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionConstructorDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionConstructorDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionEnumDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionEnumDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionEnumDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionEnumDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFactory.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFactory.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFactory.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFactory.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFieldDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFieldDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFieldDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionFieldDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionInterfaceDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionInterfaceDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionInterfaceDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionInterfaceDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodResolutionLogic.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodResolutionLogic.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodResolutionLogic.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionMethodResolutionLogic.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionParameterDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionParameterDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionParameterDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionParameterDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionTypeParameter.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionTypeParameter.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionTypeParameter.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_ReflectionTypeParameter.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ClassComparator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ClassComparator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ClassComparator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ClassComparator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_MethodComparator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_MethodComparator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_MethodComparator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_MethodComparator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ParameterComparator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ParameterComparator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ParameterComparator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_reflectionmodel_comparators_ParameterComparator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_ConstructorResolutionLogic.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_ConstructorResolutionLogic.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_ConstructorResolutionLogic.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_ConstructorResolutionLogic.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_MethodResolutionLogic.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_MethodResolutionLogic.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_MethodResolutionLogic.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_MethodResolutionLogic.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolDeclarator.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolDeclarator.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolDeclarator.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolDeclarator.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolSolver.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolSolver.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolSolver.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_SymbolSolver.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_CombinedTypeSolver.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_CombinedTypeSolver.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_CombinedTypeSolver.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_CombinedTypeSolver.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JarTypeSolver.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JarTypeSolver.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JarTypeSolver.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JarTypeSolver.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JavaParserTypeSolver.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JavaParserTypeSolver.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JavaParserTypeSolver.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_JavaParserTypeSolver.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_MemoryTypeSolver.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_MemoryTypeSolver.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_MemoryTypeSolver.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_MemoryTypeSolver.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_ReflectionTypeSolver.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_ReflectionTypeSolver.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_ReflectionTypeSolver.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_resolution_typesolvers_ReflectionTypeSolver.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractClassDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractClassDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractClassDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractTypeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractTypeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractTypeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_AbstractTypeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ConfilictingGenericTypesException.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ConfilictingGenericTypesException.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ConfilictingGenericTypesException.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ConfilictingGenericTypesException.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_FunctionalInterfaceLogic.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_FunctionalInterfaceLogic.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_FunctionalInterfaceLogic.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_FunctionalInterfaceLogic.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceContext.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceContext.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceContext.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceContext.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceVariableType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceVariableType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceVariableType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_InferenceVariableType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ObjectProvider.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ObjectProvider.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ObjectProvider.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-logic/com_github_javaparser_symbolsolver_logic_ObjectProvider.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AccessLevel.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AccessLevel.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AccessLevel.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AccessLevel.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AnnotationDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AnnotationDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AnnotationDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_AnnotationDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ClassDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ClassDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ClassDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ConstructorDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ConstructorDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ConstructorDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ConstructorDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_Declaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_Declaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_Declaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_Declaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_EnumDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_EnumDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_EnumDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_EnumDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_FieldDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_FieldDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_FieldDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_FieldDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_HasAccessLevel.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_HasAccessLevel.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_HasAccessLevel.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_HasAccessLevel.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_InterfaceDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_InterfaceDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_InterfaceDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_InterfaceDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodAmbiguityException.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodAmbiguityException.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodAmbiguityException.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodAmbiguityException.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodLikeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodLikeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodLikeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_MethodLikeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ParameterDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ParameterDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ParameterDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ParameterDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ReferenceTypeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ReferenceTypeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ReferenceTypeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ReferenceTypeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParameterDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParameterDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParameterDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParameterDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParametrizable.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParametrizable.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParametrizable.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_TypeParametrizable.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ValueDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ValueDeclaration.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ValueDeclaration.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_declarations_ValueDeclaration.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_methods_MethodUsage.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_methods_MethodUsage.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_methods_MethodUsage.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_methods_MethodUsage.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_SymbolReference.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_SymbolReference.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_SymbolReference.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_SymbolReference.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_TypeSolver.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_TypeSolver.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_TypeSolver.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_TypeSolver.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_UnsolvedSymbolException.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_UnsolvedSymbolException.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_UnsolvedSymbolException.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_UnsolvedSymbolException.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_Value.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_Value.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_Value.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_resolution_Value.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ArrayType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ArrayType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ArrayType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ArrayType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_LambdaConstraintType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_LambdaConstraintType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_LambdaConstraintType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_LambdaConstraintType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_NullType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_NullType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_NullType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_NullType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType_J9.txt
similarity index 100%
copy from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType.txt
copy to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_PrimitiveType_J9.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ReferenceType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ReferenceType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ReferenceType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_ReferenceType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Type.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Type.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Type.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Type.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeTransformer.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeTransformer.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeTransformer.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeTransformer.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeVariable.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeVariable.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeVariable.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_TypeVariable.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_VoidType.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_VoidType.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_VoidType.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_VoidType.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Wildcard.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Wildcard.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Wildcard.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_Wildcard.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParameterValueProvider.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParameterValueProvider.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParameterValueProvider.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParameterValueProvider.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametersMap.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametersMap.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametersMap.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametersMap.txt
diff --git a/javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametrized.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametrized.txt
similarity index 100%
rename from javaparser-symbol-solver-testing/src/test/resources/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametrized.txt
rename to javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-model/com_github_javaparser_symbolsolver_model_typesystem_parametrization_TypeParametrized.txt
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/guava-21.0.jar b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/guava-21.0.jar
new file mode 100644
index 0000000..0618195
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/guava-21.0.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javaparser-core-3.3.0.jar b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javaparser-core-3.3.0.jar
new file mode 100644
index 0000000..14f02f6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javaparser-core-3.3.0.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javaslang-2.0.3.jar b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javaslang-2.0.3.jar
new file mode 100644
index 0000000..d7808ea
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javaslang-2.0.3.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javassist-3.19.0-GA.jar b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javassist-3.19.0-GA.jar
new file mode 100644
index 0000000..7ac4264
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/lib/javassist-3.19.0-GA.jar
Binary files differ
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java
new file mode 100644
index 0000000..5e2bb05
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/SourceFileInfoExtractor.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseException;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.ImportDeclaration;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * It prints information extracted from a source file. It is mainly intended as an example usage of JavaSymbolSolver.
+ *
+ * @author Federico Tomassetti
+ */
+public class SourceFileInfoExtractor {
+
+    private TypeSolver typeSolver;
+
+    private int ok = 0;
+    private int ko = 0;
+    private int unsupported = 0;
+    private boolean printFileName = true;
+    private PrintStream out = System.out;
+    private PrintStream err = System.err;
+
+    public void setVerbose(boolean verbose) {
+        this.verbose = verbose;
+    }
+
+    private boolean verbose = false;
+
+    public void setPrintFileName(boolean printFileName) {
+        this.printFileName = printFileName;
+    }
+
+    public void clear() {
+        ok = 0;
+        ko = 0;
+        unsupported = 0;
+    }
+
+    public void setOut(PrintStream out) {
+        this.out = out;
+    }
+
+    public void setErr(PrintStream err) {
+        this.err = err;
+    }
+
+    public int getOk() {
+        return ok;
+
+    }
+
+    public int getUnsupported() {
+        return unsupported;
+    }
+
+    public int getKo() {
+        return ko;
+    }
+
+    private void solveTypeDecl(ClassOrInterfaceDeclaration node) {
+        TypeDeclaration typeDeclaration = JavaParserFacade.get(typeSolver).getTypeDeclaration(node);
+        if (typeDeclaration.isClass()) {
+            out.println("\n[ Class " + typeDeclaration.getQualifiedName() + " ]");
+            for (ReferenceType sc : typeDeclaration.asClass().getAllSuperClasses()) {
+                out.println("  superclass: " + sc.getQualifiedName());
+            }
+            for (ReferenceType sc : typeDeclaration.asClass().getAllInterfaces()) {
+                out.println("  interface: " + sc.getQualifiedName());
+            }
+        }
+    }
+
+    private void solve(Node node) {
+        if (node instanceof ClassOrInterfaceDeclaration) {
+            solveTypeDecl((ClassOrInterfaceDeclaration) node);
+        } else if (node instanceof Expression) {
+            if ((getParentNode(node) instanceof ImportDeclaration) || (getParentNode(node) instanceof Expression)
+                    || (getParentNode(node) instanceof MethodDeclaration)
+                    || (getParentNode(node) instanceof PackageDeclaration)) {
+                // skip
+            } else if ((getParentNode(node) instanceof Statement) || (getParentNode(node) instanceof VariableDeclarator)) {
+                try {
+                    Type ref = JavaParserFacade.get(typeSolver).getType(node);
+                    out.println("  Line " + node.getRange().get().begin.line + ") " + node + " ==> " + ref.describe());
+                    ok++;
+                } catch (UnsupportedOperationException upe) {
+                    unsupported++;
+                    err.println(upe.getMessage());
+                    throw upe;
+                } catch (RuntimeException re) {
+                    ko++;
+                    err.println(re.getMessage());
+                    throw re;
+                }
+            }
+        }
+    }
+
+    private void solveMethodCalls(Node node) {
+        if (node instanceof MethodCallExpr) {
+            out.println("  Line " + node.getBegin().get().line + ") " + node + " ==> " + toString((MethodCallExpr) node));
+        }
+        for (Node child : node.getChildNodes()) {
+            solveMethodCalls(child);
+        }
+    }
+
+    private String toString(MethodCallExpr node) {
+        try {
+            return toString(JavaParserFacade.get(typeSolver).solve(node));
+        } catch (Exception e) {
+            if (verbose) {
+                System.err.println("Error resolving call at L" + node.getBegin().get().line + ": " + node);
+                e.printStackTrace();
+            }
+            return "ERROR";
+        }
+    }
+
+    private String toString(SymbolReference<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration> methodDeclarationSymbolReference) {
+        if (methodDeclarationSymbolReference.isSolved()) {
+            return methodDeclarationSymbolReference.getCorrespondingDeclaration().getQualifiedSignature();
+        } else {
+            return "UNSOLVED";
+        }
+    }
+
+    private List<Node> collectAllNodes(Node node) {
+        List<Node> nodes = new LinkedList<>();
+        collectAllNodes(node, nodes);
+        nodes.sort((n1, n2) -> n1.getBegin().get().compareTo(n2.getBegin().get()));
+        return nodes;
+    }
+
+    private void collectAllNodes(Node node, List<Node> nodes) {
+        nodes.add(node);
+        node.getChildNodes().forEach(c -> collectAllNodes(c, nodes));
+    }
+
+    public void solve(File file) throws IOException, ParseException {
+        if (file.isDirectory()) {
+            for (File f : file.listFiles()) {
+                solve(f);
+            }
+        } else {
+            if (file.getName().endsWith(".java")) {
+                if (printFileName) {
+                    out.println("- parsing " + file.getAbsolutePath());
+                }
+                CompilationUnit cu = JavaParser.parse(file);
+                List<Node> nodes = collectAllNodes(cu);
+                nodes.forEach(n -> solve(n));
+            }
+        }
+    }
+
+    public void solveMethodCalls(File file) throws IOException, ParseException {
+        if (file.isDirectory()) {
+            for (File f : file.listFiles()) {
+                solveMethodCalls(f);
+            }
+        } else {
+            if (file.getName().endsWith(".java")) {
+                if (printFileName) {
+                    out.println("- parsing " + file.getAbsolutePath());
+                }
+                CompilationUnit cu = JavaParser.parse(file);
+                solveMethodCalls(cu);
+            }
+        }
+    }
+
+    public void setTypeSolver(TypeSolver typeSolver) {
+        this.typeSolver = typeSolver;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/core/resolution/Context.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/core/resolution/Context.java
new file mode 100644
index 0000000..4865334
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/core/resolution/Context.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.core.resolution;
+
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Context is very similar to scope.
+ * In the context we look for solving symbols.
+ *
+ * @author Federico Tomassetti
+ */
+public interface Context {
+
+    Context getParent();
+
+    /* Type resolution */
+
+    default Optional<Type> solveGenericType(String name, TypeSolver typeSolver) {
+        return Optional.empty();
+    }
+
+    default SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        Context parent = getParent();
+        if (parent == null) {
+            return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+        } else {
+            return parent.solveType(name, typeSolver);
+        }
+    }
+
+    /* Symbol resolution */
+
+    SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver);
+
+    default Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        SymbolReference<? extends ValueDeclaration> ref = solveSymbol(name, typeSolver);
+        if (ref.isSolved()) {
+            Value value = Value.from(ref.getCorrespondingDeclaration());
+            return Optional.of(value);
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    /* Constructor resolution */
+
+    /**
+     * We find the method declaration which is the best match for the given name and list of typeParametersValues.
+     */
+    default SymbolReference<ConstructorDeclaration> solveConstructor(List<Type> argumentsTypes, TypeSolver typeSolver) {
+        throw new IllegalArgumentException("Constructor resolution is available only on Class Context");
+    }
+
+    /* Methods resolution */
+
+    /**
+     * We find the method declaration which is the best match for the given name and list of typeParametersValues.
+     */
+    SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver);
+
+    /**
+     * Similar to solveMethod but we return a MethodUsage. A MethodUsage corresponds to a MethodDeclaration plus the
+     * resolved type variables.
+     */
+    default Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        SymbolReference<MethodDeclaration> methodSolved = solveMethod(name, argumentsTypes, false, typeSolver);
+        if (methodSolved.isSolved()) {
+            MethodDeclaration methodDeclaration = methodSolved.getCorrespondingDeclaration();
+            MethodUsage methodUsage = ContextHelper.resolveTypeVariables(this, methodDeclaration, argumentsTypes);//methodDeclaration.resolveTypeVariables(this, argumentsTypes);
+            return Optional.of(methodUsage);
+        } else {
+            return Optional.empty();
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/core/resolution/ContextHelper.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/core/resolution/ContextHelper.java
new file mode 100644
index 0000000..21a0d28
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/core/resolution/ContextHelper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.core.resolution;
+
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistMethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionMethodDeclaration;
+
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+class ContextHelper {
+
+    private ContextHelper() {
+        // prevent instantiation
+    }
+
+    static MethodUsage resolveTypeVariables(Context context, MethodDeclaration methodDeclaration, List<Type> parameterTypes) {
+        if (methodDeclaration instanceof JavaParserMethodDeclaration) {
+            return ((JavaParserMethodDeclaration) methodDeclaration).resolveTypeVariables(context, parameterTypes);
+        } else if (methodDeclaration instanceof JavassistMethodDeclaration) {
+            return ((JavassistMethodDeclaration) methodDeclaration).resolveTypeVariables(context, parameterTypes);
+        } else if (methodDeclaration instanceof JavaParserEnumDeclaration.ValuesMethod) {
+            return ((JavaParserEnumDeclaration.ValuesMethod) methodDeclaration).resolveTypeVariables(context, parameterTypes);
+        } else if (methodDeclaration instanceof ReflectionMethodDeclaration) {
+            return ((ReflectionMethodDeclaration) methodDeclaration).resolveTypeVariables(context, parameterTypes);
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic.java
new file mode 100644
index 0000000..a1cc469
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/declarations/common/MethodDeclarationCommonLogic.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.declarations.common;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.logic.InferenceContext;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
+import com.github.javaparser.symbolsolver.reflectionmodel.MyObjectProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class MethodDeclarationCommonLogic {
+
+    private MethodDeclaration methodDeclaration;
+    private TypeSolver typeSolver;
+
+    public MethodDeclarationCommonLogic(MethodDeclaration methodDeclaration, TypeSolver typeSolver) {
+        this.methodDeclaration = methodDeclaration;
+        this.typeSolver = typeSolver;
+    }
+
+    public MethodUsage resolveTypeVariables(Context context, List<Type> parameterTypes) {
+        Type returnType = replaceTypeParams(methodDeclaration.getReturnType(), typeSolver, context);
+        List<Type> params = new ArrayList<>();
+        for (int i = 0; i < methodDeclaration.getNumberOfParams(); i++) {
+            Type replaced = replaceTypeParams(methodDeclaration.getParam(i).getType(), typeSolver, context);
+            params.add(replaced);
+        }
+
+        // We now look at the type parameter for the method which we can derive from the parameter types
+        // and then we replace them in the return type
+        // Map<TypeParameterDeclaration, Type> determinedTypeParameters = new HashMap<>();
+        InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE);
+        for (int i = 0; i < methodDeclaration.getNumberOfParams() - (methodDeclaration.hasVariadicParameter() ? 1 : 0); i++) {
+            Type formalParamType = methodDeclaration.getParam(i).getType();
+            Type actualParamType = parameterTypes.get(i);
+            inferenceContext.addPair(formalParamType, actualParamType);
+        }
+
+        returnType = inferenceContext.resolve(inferenceContext.addSingle(returnType));
+
+        return new MethodUsage(methodDeclaration, params, returnType);
+    }
+
+    private Type replaceTypeParams(Type type, TypeSolver typeSolver, Context context) {
+        if (type.isTypeVariable()) {
+            TypeParameterDeclaration typeParameter = type.asTypeParameter();
+            if (typeParameter.declaredOnType()) {
+                Optional<Type> typeParam = typeParamByName(typeParameter.getName(), typeSolver, context);
+                if (typeParam.isPresent()) {
+                    type = typeParam.get();
+                }
+            }
+        }
+
+        if (type.isReferenceType()) {
+            type.asReferenceType().transformTypeParameters(tp -> replaceTypeParams(tp, typeSolver, context));
+        }
+
+        return type;
+    }
+
+    protected Optional<Type> typeParamByName(String name, TypeSolver typeSolver, Context context) {
+        return methodDeclaration.getTypeParameters().stream().filter(tp -> tp.getName().equals(name)).map(tp -> toType(tp)).findFirst();
+    }
+
+    protected Type toType(TypeParameterDeclaration typeParameterDeclaration) {
+        return new TypeVariable(typeParameterDeclaration);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparser/Navigator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparser/Navigator.java
new file mode 100644
index 0000000..f828bd3
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparser/Navigator.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparser;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.expr.SimpleName;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import com.github.javaparser.ast.stmt.SwitchStmt;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * This class can be used to easily retrieve nodes from a JavaParser AST.
+ *
+ * @author Federico Tomassetti
+ */
+public final class Navigator {
+
+    private Navigator() {
+        // prevent instantiation
+    }
+
+    public static Node getParentNode(Node node) {
+        Node parent = node.getParentNode().orElse(null);
+        return parent;
+    }
+
+    public static Optional<TypeDeclaration<?>> findType(CompilationUnit cu, String qualifiedName) {
+        if (cu.getTypes().isEmpty()) {
+            return Optional.empty();
+        }
+
+        final String typeName = getOuterTypeName(qualifiedName);
+        Optional<TypeDeclaration<?>> type = cu.getTypes().stream().filter((t) -> t.getName().getId().equals(typeName)).findFirst();
+
+        final String innerTypeName = getInnerTypeName(qualifiedName);
+        if (type.isPresent() && !innerTypeName.isEmpty()) {
+            return findType(type.get(), innerTypeName);
+        }
+        return type;
+    }
+
+    public static Optional<TypeDeclaration<?>> findType(TypeDeclaration<?> td, String qualifiedName) {
+        final String typeName = getOuterTypeName(qualifiedName);
+
+        Optional<TypeDeclaration<?>> type = Optional.empty();
+        for (Node n : td.getMembers()) {
+            if (n instanceof TypeDeclaration && ((TypeDeclaration<?>) n).getName().getId().equals(typeName)) {
+                type = Optional.of((TypeDeclaration<?>) n);
+                break;
+            }
+        }
+        final String innerTypeName = getInnerTypeName(qualifiedName);
+        if (type.isPresent() && !innerTypeName.isEmpty()) {
+            return findType(type.get(), innerTypeName);
+        }
+        return type;
+    }
+
+    public static ClassOrInterfaceDeclaration demandClass(CompilationUnit cu, String qualifiedName) {
+        ClassOrInterfaceDeclaration cd = demandClassOrInterface(cu, qualifiedName);
+        if (cd.isInterface()) {
+            throw new IllegalStateException("Type is not a class");
+        }
+        return cd;
+    }
+
+    public static EnumDeclaration demandEnum(CompilationUnit cu, String qualifiedName) {
+        Optional<TypeDeclaration<?>> res = findType(cu, qualifiedName);
+        if (!res.isPresent()) {
+            throw new IllegalStateException("No type found");
+        }
+        if (!(res.get() instanceof EnumDeclaration)) {
+            throw new IllegalStateException("Type is not an enum");
+        }
+        return (EnumDeclaration) res.get();
+    }
+
+    public static MethodDeclaration demandMethod(TypeDeclaration<?> cd, String name) {
+        MethodDeclaration found = null;
+        for (BodyDeclaration<?> bd : cd.getMembers()) {
+            if (bd instanceof MethodDeclaration) {
+                MethodDeclaration md = (MethodDeclaration) bd;
+                if (md.getName().getId().equals(name)) {
+                    if (found != null) {
+                        throw new IllegalStateException("Ambiguous getName");
+                    }
+                    found = md;
+                }
+            }
+        }
+        if (found == null) {
+            throw new IllegalStateException("No method with given name");
+        }
+        return found;
+    }
+
+    public static VariableDeclarator demandField(ClassOrInterfaceDeclaration cd, String name) {
+        for (BodyDeclaration<?> bd : cd.getMembers()) {
+            if (bd instanceof FieldDeclaration) {
+                FieldDeclaration fd = (FieldDeclaration) bd;
+                for (VariableDeclarator vd : fd.getVariables()) {
+                    if (vd.getName().getId().equals(name)) {
+                        return vd;
+                    }
+                }
+            }
+        }
+        throw new IllegalStateException("No field with given name");
+    }
+
+    public static NameExpr findNameExpression(Node node, String name) {
+        if (node instanceof NameExpr) {
+            NameExpr nameExpr = (NameExpr) node;
+            if (nameExpr.getName() != null && nameExpr.getName().getId().equals(name)) {
+                return nameExpr;
+            }
+        }
+        for (Node child : node.getChildNodes()) {
+            NameExpr res = findNameExpression(child, name);
+            if (res != null) {
+                return res;
+            }
+        }
+        return null;
+    }
+
+    public static SimpleName findSimpleName(Node node, String name) {
+        if (node instanceof SimpleName) {
+            SimpleName nameExpr = (SimpleName) node;
+            if (nameExpr.getId() != null && nameExpr.getId().equals(name)) {
+                return nameExpr;
+            }
+        }
+        for (Node child : node.getChildNodes()) {
+            SimpleName res = findSimpleName(child, name);
+            if (res != null) {
+                return res;
+            }
+        }
+        return null;
+    }
+
+    public static MethodCallExpr findMethodCall(Node node, String methodName) {
+        if (node instanceof MethodCallExpr) {
+            MethodCallExpr methodCallExpr = (MethodCallExpr) node;
+            if (methodCallExpr.getName().getId().equals(methodName)) {
+                return methodCallExpr;
+            }
+        }
+        for (Node child : node.getChildNodes()) {
+            MethodCallExpr res = findMethodCall(child, methodName);
+            if (res != null) {
+                return res;
+            }
+        }
+        return null;
+    }
+
+    public static VariableDeclarator demandVariableDeclaration(Node node, String name) {
+        if (node instanceof VariableDeclarator) {
+            VariableDeclarator variableDeclarator = (VariableDeclarator) node;
+            if (variableDeclarator.getName().getId().equals(name)) {
+                return variableDeclarator;
+            }
+        }
+        for (Node child : node.getChildNodes()) {
+            VariableDeclarator res = demandVariableDeclaration(child, name);
+            if (res != null) {
+                return res;
+            }
+        }
+        return null;
+    }
+
+    public static ClassOrInterfaceDeclaration demandClassOrInterface(CompilationUnit compilationUnit, String qualifiedName) {
+        Optional<TypeDeclaration<?>> res = findType(compilationUnit, qualifiedName);
+        if (!res.isPresent()) {
+            throw new IllegalStateException("No type named '" + qualifiedName + "'found");
+        }
+        if (!(res.get() instanceof ClassOrInterfaceDeclaration)) {
+            throw new IllegalStateException("Type is not a class or an interface, it is " + res.get().getClass().getCanonicalName());
+        }
+        ClassOrInterfaceDeclaration cd = (ClassOrInterfaceDeclaration) res.get();
+        return cd;
+    }
+
+    public static SwitchStmt findSwitch(Node node) {
+        SwitchStmt res = findSwitchHelper(node);
+        if (res == null) {
+            throw new IllegalArgumentException();
+        } else {
+            return res;
+        }
+    }
+
+    public static <N> N findNodeOfGivenClass(Node node, Class<N> clazz) {
+        N res = findNodeOfGivenClassHelper(node, clazz);
+        if (res == null) {
+            throw new IllegalArgumentException();
+        } else {
+            return res;
+        }
+    }
+
+    public static <N> List<N> findAllNodesOfGivenClass(Node node, Class<N> clazz) {
+        List<N> res = new LinkedList<>();
+        findAllNodesOfGivenClassHelper(node, clazz, res);
+        return res;
+    }
+
+    public static ReturnStmt findReturnStmt(MethodDeclaration method) {
+        return findNodeOfGivenClass(method, ReturnStmt.class);
+    }
+
+    public static <N extends Node> Optional<N> findAncestor(Node node, Class<N> clazz) {
+        if (!node.getParentNode().isPresent()) {
+            return Optional.empty();
+        } else if (clazz.isInstance(node.getParentNode().get())) {
+            return Optional.of(clazz.cast(node.getParentNode().get()));
+        } else {
+            return findAncestor(node.getParentNode().get(), clazz);
+        }
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private static String getOuterTypeName(String qualifiedName) {
+        return qualifiedName.split("\\.", 2)[0];
+    }
+
+    private static String getInnerTypeName(String qualifiedName) {
+        if (qualifiedName.contains(".")) {
+            return qualifiedName.split("\\.", 2)[1];
+        }
+        return "";
+    }
+
+    private static SwitchStmt findSwitchHelper(Node node) {
+        if (node instanceof SwitchStmt) {
+            return (SwitchStmt) node;
+        }
+        for (Node child : node.getChildNodes()) {
+            SwitchStmt resChild = findSwitchHelper(child);
+            if (resChild != null) {
+                return resChild;
+            }
+        }
+        return null;
+    }
+
+    private static <N> N findNodeOfGivenClassHelper(Node node, Class<N> clazz) {
+        if (clazz.isInstance(node)) {
+            return clazz.cast(node);
+        }
+        for (Node child : node.getChildNodes()) {
+            N resChild = findNodeOfGivenClassHelper(child, clazz);
+            if (resChild != null) {
+                return resChild;
+            }
+        }
+        return null;
+    }
+
+    private static <N> void findAllNodesOfGivenClassHelper(Node node, Class<N> clazz, List<N> collector) {
+        if (clazz.isInstance(node)) {
+            collector.add(clazz.cast(node));
+        }
+        for (Node child : node.getChildNodes()) {
+            findAllNodesOfGivenClassHelper(child, clazz, collector);
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparser/package-info.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparser/package-info.java
new file mode 100644
index 0000000..16ef202
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparser/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This package contains utility to use JavaParser.
+ */
+package com.github.javaparser.symbolsolver.javaparser;
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java
new file mode 100644
index 0000000..de13d1f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/DefaultVisitorAdapter.java
@@ -0,0 +1,465 @@
+package com.github.javaparser.symbolsolver.javaparsermodel;
+
+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.expr.*;
+import com.github.javaparser.ast.modules.*;
+import com.github.javaparser.ast.stmt.*;
+import com.github.javaparser.ast.type.*;
+import com.github.javaparser.ast.visitor.GenericVisitor;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+public class DefaultVisitorAdapter implements GenericVisitor<Type, Boolean> {
+    @Override
+    public Type visit(CompilationUnit node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(PackageDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(TypeParameter node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(LineComment node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(BlockComment node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ClassOrInterfaceDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(EnumDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(EnumConstantDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(AnnotationDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(AnnotationMemberDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(FieldDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(VariableDeclarator node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ConstructorDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(MethodDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(Parameter node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(InitializerDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(JavadocComment node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ClassOrInterfaceType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(PrimitiveType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ArrayType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ArrayCreationLevel node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(IntersectionType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(UnionType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(VoidType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(WildcardType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(UnknownType node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ArrayAccessExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ArrayCreationExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ArrayInitializerExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(AssignExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(BinaryExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(CastExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ClassExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ConditionalExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(EnclosedExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(FieldAccessExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(InstanceOfExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(StringLiteralExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(IntegerLiteralExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(LongLiteralExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(CharLiteralExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(DoubleLiteralExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(BooleanLiteralExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(NullLiteralExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(MethodCallExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(NameExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ObjectCreationExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ThisExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(SuperExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(UnaryExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(VariableDeclarationExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(MarkerAnnotationExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(SingleMemberAnnotationExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(NormalAnnotationExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(MemberValuePair node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ExplicitConstructorInvocationStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(LocalClassDeclarationStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(AssertStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(BlockStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(LabeledStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(EmptyStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ExpressionStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(SwitchStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(SwitchEntryStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(BreakStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ReturnStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(IfStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(WhileStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ContinueStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(DoStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ForeachStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ForStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ThrowStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(SynchronizedStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(TryStmt node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(CatchClause node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(LambdaExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(MethodReferenceExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(TypeExpr node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(NodeList node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(Name node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(SimpleName node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ImportDeclaration node, Boolean aBoolean) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ModuleDeclaration node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ModuleRequiresStmt node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ModuleExportsStmt node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ModuleProvidesStmt node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ModuleUsesStmt node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(ModuleOpensStmt node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(UnparsableStmt node, Boolean arg) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java
new file mode 100644
index 0000000..e98eb10
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.ast.type.UnknownType;
+import com.github.javaparser.ast.type.WildcardType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.*;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.declarations.AnnotationDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+import com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+
+import java.util.*;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * Class to be used by final users to solve symbols for JavaParser ASTs.
+ *
+ * @author Federico Tomassetti
+ */
+public class JavaParserFacade {
+
+    private static Logger logger = Logger.getLogger(JavaParserFacade.class.getCanonicalName());
+
+    static {
+        logger.setLevel(Level.INFO);
+        ConsoleHandler consoleHandler = new ConsoleHandler();
+        consoleHandler.setLevel(Level.INFO);
+        logger.addHandler(consoleHandler);
+    }
+
+    private static Map<TypeSolver, JavaParserFacade> instances = new WeakHashMap<>();
+    private TypeSolver typeSolver;
+    private SymbolSolver symbolSolver;
+    private Map<Node, Type> cacheWithLambdasSolved = new IdentityHashMap<>();
+    private Map<Node, Type> cacheWithoutLambdasSolved = new IdentityHashMap<>();
+    private TypeExtractor typeExtractor;
+
+    private JavaParserFacade(TypeSolver typeSolver) {
+        this.typeSolver = typeSolver.getRoot();
+        this.symbolSolver = new SymbolSolver(typeSolver);
+        this.typeExtractor = new TypeExtractor(typeSolver, this);
+    }
+
+    public TypeSolver getTypeSolver() {
+        return typeSolver;
+    }
+
+    public SymbolSolver getSymbolSolver() {
+        return symbolSolver;
+    }
+
+    public static JavaParserFacade get(TypeSolver typeSolver) {
+        return instances.computeIfAbsent(typeSolver, JavaParserFacade::new);
+    }
+
+    /**
+     * This method is used to clear internal caches for the sake of releasing memory.
+     */
+    public static void clearInstances() {
+        instances.clear();
+    }
+
+    protected static Type solveGenericTypes(Type type, Context context, TypeSolver typeSolver) {
+        if (type.isTypeVariable()) {
+            Optional<Type> solved = context.solveGenericType(type.describe(), typeSolver);
+            if (solved.isPresent()) {
+                return solved.get();
+            } else {
+                return type;
+            }
+        } else if (type.isWildcard()) {
+            if (type.asWildcard().isExtends() || type.asWildcard().isSuper()) {
+                Wildcard wildcardUsage = type.asWildcard();
+                Type boundResolved = solveGenericTypes(wildcardUsage.getBoundedType(), context, typeSolver);
+                if (wildcardUsage.isExtends()) {
+                    return Wildcard.extendsBound(boundResolved);
+                } else {
+                    return Wildcard.superBound(boundResolved);
+                }
+            } else {
+                return type;
+            }
+        } else {
+            Type result = type;
+            return result;
+        }
+    }
+
+    public SymbolReference<? extends ValueDeclaration> solve(NameExpr nameExpr) {
+        return symbolSolver.solveSymbol(nameExpr.getName().getId(), nameExpr);
+    }
+
+    public SymbolReference<? extends ValueDeclaration> solve(SimpleName nameExpr) {
+        return symbolSolver.solveSymbol(nameExpr.getId(), nameExpr);
+    }
+
+    public SymbolReference<? extends ValueDeclaration> solve(Expression expr) {
+        if (expr instanceof NameExpr) {
+            return solve((NameExpr) expr);
+        } else {
+            throw new IllegalArgumentException(expr.getClass().getCanonicalName());
+        }
+    }
+
+    public SymbolReference<MethodDeclaration> solve(MethodCallExpr methodCallExpr) {
+        return solve(methodCallExpr, true);
+    }
+
+    public SymbolReference<ConstructorDeclaration> solve(ObjectCreationExpr objectCreationExpr) {
+        return solve(objectCreationExpr, true);
+    }
+
+    public SymbolReference<ConstructorDeclaration> solve(ExplicitConstructorInvocationStmt explicitConstructorInvocationStmt) {
+        return solve(explicitConstructorInvocationStmt, true);
+    }
+
+    public SymbolReference<ConstructorDeclaration> solve(ExplicitConstructorInvocationStmt explicitConstructorInvocationStmt, boolean solveLambdas) {
+        List<Type> argumentTypes = new LinkedList<>();
+        List<LambdaArgumentTypePlaceholder> placeholders = new LinkedList<>();
+
+        solveArguments(explicitConstructorInvocationStmt, explicitConstructorInvocationStmt.getArguments(), solveLambdas, argumentTypes, placeholders);
+
+        Optional<ClassOrInterfaceDeclaration> optAncestor = explicitConstructorInvocationStmt.getAncestorOfType(ClassOrInterfaceDeclaration.class);
+        if (!optAncestor.isPresent()) {
+            return SymbolReference.unsolved(ConstructorDeclaration.class);
+        }
+        ClassOrInterfaceDeclaration classNode = optAncestor.get();
+        TypeDeclaration typeDecl = null;
+        if (!explicitConstructorInvocationStmt.isThis()) {
+            Type classDecl = JavaParserFacade.get(typeSolver).convert(classNode.getExtendedTypes(0), classNode);
+            if (classDecl.isReferenceType()) {
+                typeDecl = classDecl.asReferenceType().getTypeDeclaration();
+            }
+        } else {
+            SymbolReference<TypeDeclaration> sr = JavaParserFactory.getContext(classNode, typeSolver).solveType(classNode.getNameAsString(), typeSolver);
+            if (sr.isSolved()) {
+                typeDecl = sr.getCorrespondingDeclaration();
+            }
+        }
+        if (typeDecl == null) {
+            return SymbolReference.unsolved(ConstructorDeclaration.class);
+        }
+        SymbolReference<ConstructorDeclaration> res = ConstructorResolutionLogic.findMostApplicable(((ClassDeclaration) typeDecl).getConstructors(), argumentTypes, typeSolver);
+        for (LambdaArgumentTypePlaceholder placeholder : placeholders) {
+            placeholder.setMethod(res);
+        }
+        return res;
+    }
+
+    public SymbolReference<TypeDeclaration> solve(ThisExpr node){
+        // If 'this' is prefixed by a class eg. MyClass.this
+        if (node.getClassExpr().isPresent()){
+            // Get the class name
+            String className = node.getClassExpr().get().toString();
+            // Attempt to resolve using a typeSolver
+            SymbolReference<ReferenceTypeDeclaration> clazz = typeSolver.tryToSolveType(className);
+            if (clazz.isSolved()){
+                return SymbolReference.solved(clazz.getCorrespondingDeclaration());
+            }
+            // Attempt to resolve locally in Compilation unit
+            Optional<CompilationUnit> cu = node.getAncestorOfType(CompilationUnit.class);
+            if (cu.isPresent()){
+                Optional<ClassOrInterfaceDeclaration> classByName = cu.get().getClassByName(className);
+                if (classByName.isPresent()){
+                    return SymbolReference.solved(getTypeDeclaration(classByName.get()));
+                }
+            }
+        }
+        return SymbolReference.solved(getTypeDeclaration(findContainingTypeDecl(node)));
+    }
+
+    /**
+     * Given a constructor call find out to which constructor declaration it corresponds.
+     */
+    public SymbolReference<ConstructorDeclaration> solve(ObjectCreationExpr objectCreationExpr, boolean solveLambdas) {
+        List<Type> argumentTypes = new LinkedList<>();
+        List<LambdaArgumentTypePlaceholder> placeholders = new LinkedList<>();
+
+        solveArguments(objectCreationExpr, objectCreationExpr.getArguments(), solveLambdas, argumentTypes, placeholders);
+
+        Type classDecl = JavaParserFacade.get(typeSolver).convert(objectCreationExpr.getType(), objectCreationExpr);
+        if (!classDecl.isReferenceType()) {
+            return SymbolReference.unsolved(ConstructorDeclaration.class);
+        }
+        SymbolReference<ConstructorDeclaration> res = ConstructorResolutionLogic.findMostApplicable(((ClassDeclaration) classDecl.asReferenceType().getTypeDeclaration()).getConstructors(), argumentTypes, typeSolver);
+        for (LambdaArgumentTypePlaceholder placeholder : placeholders) {
+            placeholder.setMethod(res);
+        }
+        return res;
+    }
+
+    private void solveArguments(Node node, NodeList<Expression> args, boolean solveLambdas, List<Type> argumentTypes, List<LambdaArgumentTypePlaceholder> placeholders) {
+        int i = 0;
+        for (Expression parameterValue : args) {
+            if (parameterValue instanceof LambdaExpr || parameterValue instanceof MethodReferenceExpr) {
+                LambdaArgumentTypePlaceholder placeholder = new LambdaArgumentTypePlaceholder(i);
+                argumentTypes.add(placeholder);
+                placeholders.add(placeholder);
+            } else {
+                try {
+                    argumentTypes.add(JavaParserFacade.get(typeSolver).getType(parameterValue, solveLambdas));
+                } catch (UnsolvedSymbolException e) {
+                    throw e;
+                } catch (Exception e) {
+                    throw new RuntimeException(String.format("Unable to calculate the type of a parameter of a method call. Method call: %s, Parameter: %s",
+                            node, parameterValue), e);
+                }
+            }
+            i++;
+        }
+    }
+
+    /**
+     * Given a method call find out to which method declaration it corresponds.
+     */
+    public SymbolReference<MethodDeclaration> solve(MethodCallExpr methodCallExpr, boolean solveLambdas) {
+        List<Type> argumentTypes = new LinkedList<>();
+        List<LambdaArgumentTypePlaceholder> placeholders = new LinkedList<>();
+
+        solveArguments(methodCallExpr, methodCallExpr.getArguments(), solveLambdas, argumentTypes, placeholders);
+
+        SymbolReference<MethodDeclaration> res = JavaParserFactory.getContext(methodCallExpr, typeSolver).solveMethod(methodCallExpr.getName().getId(), argumentTypes, false, typeSolver);
+        for (LambdaArgumentTypePlaceholder placeholder : placeholders) {
+            placeholder.setMethod(res);
+        }
+        return res;
+    }
+
+    public SymbolReference<AnnotationDeclaration> solve(AnnotationExpr annotationExpr) {
+        Context context = JavaParserFactory.getContext(annotationExpr, typeSolver);
+        SymbolReference<TypeDeclaration> typeDeclarationSymbolReference = context.solveType(annotationExpr.getNameAsString(), typeSolver);
+        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration();
+        if (typeDeclarationSymbolReference.isSolved()) {
+            return SymbolReference.solved(annotationDeclaration);
+        } else {
+            return SymbolReference.unsolved(AnnotationDeclaration.class);
+        }
+    }
+
+    public Type getType(Node node) {
+        return getType(node, true);
+    }
+
+    public Type getType(Node node, boolean solveLambdas) {
+        if (solveLambdas) {
+            if (!cacheWithLambdasSolved.containsKey(node)) {
+                Type res = getTypeConcrete(node, solveLambdas);
+
+                cacheWithLambdasSolved.put(node, res);
+
+                boolean secondPassNecessary = false;
+                if (node instanceof MethodCallExpr) {
+                    MethodCallExpr methodCallExpr = (MethodCallExpr) node;
+                    for (Node arg : methodCallExpr.getArguments()) {
+                        if (!cacheWithLambdasSolved.containsKey(arg)) {
+                            getType(arg, true);
+                            secondPassNecessary = true;
+                        }
+                    }
+                }
+                if (secondPassNecessary) {
+                    cacheWithLambdasSolved.remove(node);
+                    cacheWithLambdasSolved.put(node, getType(node, true));
+                }
+                logger.finer("getType on " + node + " -> " + res);
+            }
+            return cacheWithLambdasSolved.get(node);
+        } else {
+            Optional<Type> res = find(cacheWithLambdasSolved, node);
+            if (res.isPresent()) {
+                return res.get();
+            }
+            res = find(cacheWithoutLambdasSolved, node);
+            if (!res.isPresent()) {
+                Type resType = getTypeConcrete(node, solveLambdas);
+                cacheWithoutLambdasSolved.put(node, resType);
+                logger.finer("getType on " + node + " (no solveLambdas) -> " + res);
+                return resType;
+            }
+            return res.get();
+        }
+    }
+
+    private Optional<Type> find(Map<Node, Type> map, Node node) {
+        if (map.containsKey(node)) {
+            return Optional.of(map.get(node));
+        }
+        if (node instanceof LambdaExpr) {
+            return find(map, (LambdaExpr) node);
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * For some reasons LambdaExprs are duplicate and the equals method is not implemented correctly.
+     *
+     * @param map
+     * @return
+     */
+    private Optional<Type> find(Map<Node, Type> map, LambdaExpr lambdaExpr) {
+        for (Node key : map.keySet()) {
+            if (key instanceof LambdaExpr) {
+                LambdaExpr keyLambdaExpr = (LambdaExpr) key;
+                if (keyLambdaExpr.toString().equals(lambdaExpr.toString()) && getParentNode(keyLambdaExpr) == getParentNode(lambdaExpr)) {
+                    return Optional.of(map.get(keyLambdaExpr));
+                }
+            }
+        }
+        return Optional.empty();
+    }
+
+    protected MethodUsage toMethodUsage(MethodReferenceExpr methodReferenceExpr) {
+        if (!(methodReferenceExpr.getScope() instanceof TypeExpr)) {
+            throw new UnsupportedOperationException();
+        }
+        TypeExpr typeExpr = (TypeExpr) methodReferenceExpr.getScope();
+        if (!(typeExpr.getType() instanceof com.github.javaparser.ast.type.ClassOrInterfaceType)) {
+            throw new UnsupportedOperationException(typeExpr.getType().getClass().getCanonicalName());
+        }
+        ClassOrInterfaceType classOrInterfaceType = (ClassOrInterfaceType) typeExpr.getType();
+        SymbolReference<TypeDeclaration> typeDeclarationSymbolReference = JavaParserFactory.getContext(classOrInterfaceType, typeSolver).solveType(classOrInterfaceType.getName().getId(), typeSolver);
+        if (!typeDeclarationSymbolReference.isSolved()) {
+            throw new UnsupportedOperationException();
+        }
+        List<MethodUsage> methodUsages = ((ReferenceTypeDeclaration) typeDeclarationSymbolReference.getCorrespondingDeclaration()).getAllMethods().stream().filter(it -> it.getName().equals(methodReferenceExpr.getIdentifier())).collect(Collectors.toList());
+        switch (methodUsages.size()) {
+            case 0:
+                throw new UnsupportedOperationException();
+            case 1:
+                return methodUsages.get(0);
+            default:
+                throw new UnsupportedOperationException();
+        }
+    }
+
+    protected Type getBinaryTypeConcrete(Node left, Node right, boolean solveLambdas) {
+        Type leftType = getTypeConcrete(left, solveLambdas);
+        Type rightType = getTypeConcrete(right, solveLambdas);
+        if (rightType.isAssignableBy(leftType)) {
+            return rightType;
+        }
+        return leftType;
+    }
+
+
+    /**
+     * Should return more like a TypeApplication: a TypeDeclaration and possible typeParametersValues or array
+     * modifiers.
+     *
+     * @return
+     */
+    private Type getTypeConcrete(Node node, boolean solveLambdas) {
+        if (node == null) throw new IllegalArgumentException();
+        return node.accept(typeExtractor, solveLambdas);
+    }
+
+    protected com.github.javaparser.ast.body.TypeDeclaration<?> findContainingTypeDecl(Node node) {
+        if (node instanceof ClassOrInterfaceDeclaration) {
+            return (ClassOrInterfaceDeclaration) node;
+        } else if (node instanceof EnumDeclaration) {
+            return (EnumDeclaration) node;
+        } else if (getParentNode(node) == null) {
+            throw new IllegalArgumentException();
+        } else {
+            return findContainingTypeDecl(getParentNode(node));
+        }
+    }
+
+    public Type convertToUsageVariableType(VariableDeclarator var) {
+        Type type = JavaParserFacade.get(typeSolver).convertToUsage(var.getType(), var);
+        return type;
+    }
+
+    public Type convertToUsage(com.github.javaparser.ast.type.Type type, Node context) {
+        if (type instanceof UnknownType) {
+            throw new IllegalArgumentException("Unknown type");
+        }
+        return convertToUsage(type, JavaParserFactory.getContext(context, typeSolver));
+    }
+
+    public Type convertToUsage(com.github.javaparser.ast.type.Type type) {
+        return convertToUsage(type, type);
+    }
+
+    // This is an hack around an issue in JavaParser
+    private String qName(ClassOrInterfaceType classOrInterfaceType) {
+        String name = classOrInterfaceType.getName().getId();
+        if (classOrInterfaceType.getScope().isPresent()) {
+            return qName(classOrInterfaceType.getScope().get()) + "." + name;
+        } else {
+            return name;
+        }
+    }
+
+    protected Type convertToUsage(com.github.javaparser.ast.type.Type type, Context context) {
+        if (type instanceof ClassOrInterfaceType) {
+            ClassOrInterfaceType classOrInterfaceType = (ClassOrInterfaceType) type;
+            String name = qName(classOrInterfaceType);
+            SymbolReference<TypeDeclaration> ref = context.solveType(name, typeSolver);
+            if (!ref.isSolved()) {
+                throw new UnsolvedSymbolException(name);
+            }
+            TypeDeclaration typeDeclaration = ref.getCorrespondingDeclaration();
+            List<Type> typeParameters = Collections.emptyList();
+            if (classOrInterfaceType.getTypeArguments().isPresent()) {
+                typeParameters = classOrInterfaceType.getTypeArguments().get().stream().map((pt) -> convertToUsage(pt, context)).collect(Collectors.toList());
+            }
+            if (typeDeclaration.isTypeParameter()) {
+                if (typeDeclaration instanceof TypeParameterDeclaration) {
+                    return new TypeVariable((TypeParameterDeclaration) typeDeclaration);
+                } else {
+                    JavaParserTypeVariableDeclaration javaParserTypeVariableDeclaration = (JavaParserTypeVariableDeclaration) typeDeclaration;
+                    return new TypeVariable(javaParserTypeVariableDeclaration.asTypeParameter());
+                }
+            } else {
+                return new ReferenceTypeImpl((ReferenceTypeDeclaration) typeDeclaration, typeParameters, typeSolver);
+            }
+        } else if (type instanceof com.github.javaparser.ast.type.PrimitiveType) {
+            return PrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) type).getType().name());
+        } else if (type instanceof WildcardType) {
+            WildcardType wildcardType = (WildcardType) type;
+            if (wildcardType.getExtendedTypes().isPresent() && !wildcardType.getSuperTypes().isPresent()) {
+                return Wildcard.extendsBound(convertToUsage(wildcardType.getExtendedTypes().get(), context)); // removed (ReferenceTypeImpl)
+            } else if (!wildcardType.getExtendedTypes().isPresent() && wildcardType.getSuperTypes().isPresent()) {
+                return Wildcard.superBound(convertToUsage(wildcardType.getSuperTypes().get(), context)); // removed (ReferenceTypeImpl)
+            } else if (!wildcardType.getExtendedTypes().isPresent() && !wildcardType.getSuperTypes().isPresent()) {
+                return Wildcard.UNBOUNDED;
+            } else {
+                throw new UnsupportedOperationException(wildcardType.toString());
+            }
+        } else if (type instanceof com.github.javaparser.ast.type.VoidType) {
+            return VoidType.INSTANCE;
+        } else if (type instanceof com.github.javaparser.ast.type.ArrayType) {
+            com.github.javaparser.ast.type.ArrayType jpArrayType = (com.github.javaparser.ast.type.ArrayType) type;
+            return new ArrayType(convertToUsage(jpArrayType.getComponentType(), context));
+        } else {
+            throw new UnsupportedOperationException(type.getClass().getCanonicalName());
+        }
+    }
+
+
+    public Type convert(com.github.javaparser.ast.type.Type type, Node node) {
+        return convert(type, JavaParserFactory.getContext(node, typeSolver));
+    }
+
+    public Type convert(com.github.javaparser.ast.type.Type type, Context context) {
+        return convertToUsage(type, context);
+    }
+
+    public MethodUsage solveMethodAsUsage(MethodCallExpr call) {
+        List<Type> params = new ArrayList<>();
+        if (call.getArguments() != null) {
+            for (Expression param : call.getArguments()) {
+                //getTypeConcrete(Node node, boolean solveLambdas)
+                try {
+                    params.add(getType(param, false));
+                } catch (Exception e) {
+                    throw new RuntimeException(String.format("Error calculating the type of parameter %s of method call %s", param, call), e);
+                }
+                //params.add(getTypeConcrete(param, false));
+            }
+        }
+        Context context = JavaParserFactory.getContext(call, typeSolver);
+        Optional<MethodUsage> methodUsage = context.solveMethodAsUsage(call.getName().getId(), params, typeSolver);
+        if (!methodUsage.isPresent()) {
+            throw new RuntimeException("Method '" + call.getName() + "' cannot be resolved in context "
+                    + call + " (line: " + call.getRange().get().begin.line + ") " + context + ". Parameter types: " + params);
+        }
+        return methodUsage.get();
+    }
+
+    public ReferenceTypeDeclaration getTypeDeclaration(ClassOrInterfaceDeclaration classOrInterfaceDeclaration) {
+        return JavaParserFactory.toTypeDeclaration(classOrInterfaceDeclaration, typeSolver);
+    }
+
+    /**
+     * "this" inserted in the given point, which type would have?
+     */
+    public Type getTypeOfThisIn(Node node) {
+        // TODO consider static methods
+        if (node instanceof ClassOrInterfaceDeclaration) {
+            return new ReferenceTypeImpl(getTypeDeclaration((ClassOrInterfaceDeclaration) node), typeSolver);
+        } else if (node instanceof EnumDeclaration) {
+            JavaParserEnumDeclaration enumDeclaration = new JavaParserEnumDeclaration((EnumDeclaration) node, typeSolver);
+            return new ReferenceTypeImpl(enumDeclaration, typeSolver);
+        } else {
+            return getTypeOfThisIn(getParentNode(node));
+        }
+    }
+
+    public ReferenceTypeDeclaration getTypeDeclaration(com.github.javaparser.ast.body.TypeDeclaration<?> typeDeclaration) {
+        return JavaParserFactory.toTypeDeclaration(typeDeclaration, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java
new file mode 100644
index 0000000..132c752
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFactory.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.stmt.*;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.contexts.*;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarators.FieldSymbolDeclarator;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarators.NoSymbolDeclarator;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarators.ParameterSymbolDeclarator;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarators.VariableSymbolDeclarator;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserFactory {
+
+    public static Context getContext(Node node, TypeSolver typeSolver) {
+        if (node == null) {
+            return null;
+        } else if (node instanceof CompilationUnit) {
+            return new CompilationUnitContext((CompilationUnit) node, typeSolver);
+        } else if (node instanceof ForeachStmt) {
+            return new ForechStatementContext((ForeachStmt) node, typeSolver);
+        } else if (node instanceof ForStmt) {
+            return new ForStatementContext((ForStmt) node, typeSolver);
+        } else if (node instanceof LambdaExpr) {
+            return new LambdaExprContext((LambdaExpr) node, typeSolver);
+        } else if (node instanceof MethodDeclaration) {
+            return new MethodContext((MethodDeclaration) node, typeSolver);
+        } else if (node instanceof ConstructorDeclaration) {
+            return new ConstructorContext((ConstructorDeclaration) node, typeSolver);
+        } else if (node instanceof ClassOrInterfaceDeclaration) {
+            return new ClassOrInterfaceDeclarationContext((ClassOrInterfaceDeclaration) node, typeSolver);
+        } else if (node instanceof MethodCallExpr) {
+            return new MethodCallExprContext((MethodCallExpr) node, typeSolver);
+        } else if (node instanceof EnumDeclaration) {
+            return new EnumDeclarationContext((EnumDeclaration) node, typeSolver);
+        } else if (node instanceof FieldAccessExpr) {
+            return new FieldAccessContext((FieldAccessExpr) node, typeSolver);
+        } else if (node instanceof SwitchEntryStmt) {
+            return new SwitchEntryContext((SwitchEntryStmt) node, typeSolver);
+        } else if (node instanceof TryStmt) {
+            return new TryWithResourceContext((TryStmt) node, typeSolver);
+        } else if (node instanceof Statement) {
+            return new StatementContext<Statement>((Statement) node, typeSolver);
+        } else if (node instanceof CatchClause) {
+            return new CatchClauseContext((CatchClause) node, typeSolver);
+        } else if (node instanceof ObjectCreationExpr &&
+            ((ObjectCreationExpr) node).getAnonymousClassBody().isPresent()) {
+            return new AnonymousClassDeclarationContext((ObjectCreationExpr) node, typeSolver);
+        } else {
+            if (node instanceof NameExpr) {
+                // to resolve a name when in a fieldAccess context, we can get to the grand parent to prevent a infinite loop if the name is the same as the field (ie x.x)
+                if (node.getParentNode().isPresent() && node.getParentNode().get() instanceof FieldAccessExpr && node.getParentNode().get().getParentNode().isPresent()) {
+                    return getContext(node.getParentNode().get().getParentNode().get(), typeSolver);
+                }
+            }
+            final Node parentNode = getParentNode(node);
+            if(parentNode instanceof ObjectCreationExpr && node == ((ObjectCreationExpr) parentNode).getType()) {
+                return getContext(getParentNode(parentNode), typeSolver);
+            }
+            return getContext(parentNode, typeSolver);
+        }
+    }
+
+    public static SymbolDeclarator getSymbolDeclarator(Node node, TypeSolver typeSolver) {
+        if (node instanceof FieldDeclaration) {
+            return new FieldSymbolDeclarator((FieldDeclaration) node, typeSolver);
+        } else if (node instanceof Parameter) {
+            return new ParameterSymbolDeclarator((Parameter) node, typeSolver);
+        } else if (node instanceof ExpressionStmt) {
+            ExpressionStmt expressionStmt = (ExpressionStmt) node;
+            if (expressionStmt.getExpression() instanceof VariableDeclarationExpr) {
+                return new VariableSymbolDeclarator((VariableDeclarationExpr) (expressionStmt.getExpression()), typeSolver);
+            } else {
+                return new NoSymbolDeclarator<ExpressionStmt>(expressionStmt, typeSolver);
+            }
+        } else if (node instanceof IfStmt) {
+            return new NoSymbolDeclarator<IfStmt>((IfStmt) node, typeSolver);
+        } else if (node instanceof ForeachStmt) {
+            ForeachStmt foreachStmt = (ForeachStmt) node;
+            return new VariableSymbolDeclarator((VariableDeclarationExpr) (foreachStmt.getVariable()), typeSolver);
+        } else {
+            return new NoSymbolDeclarator<Node>(node, typeSolver);
+        }
+    }
+    
+    public static ReferenceTypeDeclaration toTypeDeclaration(Node node, TypeSolver typeSolver) {
+        if (node instanceof ClassOrInterfaceDeclaration) {
+            if (((ClassOrInterfaceDeclaration) node).isInterface()) {
+                return new JavaParserInterfaceDeclaration((ClassOrInterfaceDeclaration) node, typeSolver);
+            } else {
+                return new JavaParserClassDeclaration((ClassOrInterfaceDeclaration) node, typeSolver);
+            }
+        } else if (node instanceof TypeParameter) {
+            return new JavaParserTypeParameter((TypeParameter) node, typeSolver);
+        } else if (node instanceof EnumDeclaration) {
+            return new JavaParserEnumDeclaration((EnumDeclaration) node, typeSolver);
+        } else if (node instanceof AnnotationDeclaration) {
+            return new JavaParserAnnotationDeclaration((AnnotationDeclaration) node, typeSolver);
+        } else {
+            throw new IllegalArgumentException(node.getClass().getCanonicalName());
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder.java
new file mode 100644
index 0000000..22b55b4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/LambdaArgumentTypePlaceholder.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+/**
+ * Placeholder used to represent a lambda argument type while it is being
+ * calculated.
+ *
+ * @author Federico Tomassetti
+ */
+public class LambdaArgumentTypePlaceholder implements Type {
+
+    private int pos;
+    private SymbolReference<? extends MethodLikeDeclaration> method;
+
+    public LambdaArgumentTypePlaceholder(int pos) {
+        this.pos = pos;
+    }
+
+    @Override
+    public boolean isArray() {
+        return false;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    @Override
+    public boolean isReferenceType() {
+        return false;
+    }
+
+    @Override
+    public String describe() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isTypeVariable() {
+        return false;
+    }
+
+    public void setMethod(SymbolReference<? extends MethodLikeDeclaration> method) {
+        this.method = method;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        throw new UnsupportedOperationException();
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java
new file mode 100644
index 0000000..2048e6c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/TypeExtractor.java
@@ -0,0 +1,523 @@
+package com.github.javaparser.symbolsolver.javaparsermodel;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.*;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ExpressionStmt;
+import com.github.javaparser.ast.stmt.ReturnStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.type.UnknownType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic;
+import com.github.javaparser.symbolsolver.logic.InferenceContext;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+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.typesolvers.ReflectionTypeSolver;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+public class TypeExtractor extends DefaultVisitorAdapter {
+
+    private static Logger logger = Logger.getLogger(TypeExtractor.class.getCanonicalName());
+
+    static {
+        logger.setLevel(Level.INFO);
+        ConsoleHandler consoleHandler = new ConsoleHandler();
+        consoleHandler.setLevel(Level.INFO);
+        logger.addHandler(consoleHandler);
+    }
+
+    private TypeSolver typeSolver;
+    private JavaParserFacade facade;
+
+    public TypeExtractor(TypeSolver typeSolver, JavaParserFacade facade) {
+        this.typeSolver = typeSolver;
+        this.facade = facade;
+    }
+
+    @Override
+    public Type visit(VariableDeclarator node, Boolean solveLambdas) {
+        if (getParentNode(node) instanceof FieldDeclaration) {
+//                FieldDeclaration parent = (FieldDeclaration) getParentNode(node);
+            return facade.convertToUsageVariableType(node);
+        } else if (getParentNode(node) instanceof VariableDeclarationExpr) {
+//                VariableDeclarationExpr parent = (VariableDeclarationExpr) getParentNode(node);
+            return facade.convertToUsageVariableType(node);
+        } else {
+            throw new UnsupportedOperationException(getParentNode(node).getClass().getCanonicalName());
+        }
+    }
+
+    @Override
+    public Type visit(Parameter node, Boolean solveLambdas) {
+        if (node.getType() instanceof UnknownType) {
+            throw new IllegalStateException("Parameter has unknown type: " + node);
+        }
+        return facade.convertToUsage(node.getType(), node);
+    }
+
+
+    @Override
+    public Type visit(ArrayAccessExpr node, Boolean solveLambdas) {
+        Type arrayUsageType = node.getName().accept(this, solveLambdas);
+        if (arrayUsageType.isArray()) {
+            return ((ArrayType) arrayUsageType).getComponentType();
+        }
+        return arrayUsageType;
+    }
+
+    @Override
+    public Type visit(ArrayCreationExpr node, Boolean solveLambdas) {
+        Type res = facade.convertToUsage(node.getElementType(), JavaParserFactory.getContext(node, typeSolver));
+        for (int i = 0; i < node.getLevels().size(); i++) {
+            res = new ArrayType(res);
+        }
+        return res;
+    }
+
+    @Override
+    public Type visit(ArrayInitializerExpr node, Boolean solveLambdas) {
+        throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+    }
+
+    @Override
+    public Type visit(AssignExpr node, Boolean solveLambdas) {
+        return node.getTarget().accept(this, solveLambdas);
+    }
+
+    @Override
+    public Type visit(BinaryExpr node, Boolean solveLambdas) {
+        switch (node.getOperator()) {
+            case PLUS:
+            case MINUS:
+            case DIVIDE:
+            case MULTIPLY:
+                return facade.getBinaryTypeConcrete(node.getLeft(), node.getRight(), solveLambdas);
+            case LESS_EQUALS:
+            case LESS:
+            case GREATER:
+            case GREATER_EQUALS:
+            case EQUALS:
+            case NOT_EQUALS:
+            case OR:
+            case AND:
+                return PrimitiveType.BOOLEAN;
+            case BINARY_AND:
+            case BINARY_OR:
+            case SIGNED_RIGHT_SHIFT:
+            case UNSIGNED_RIGHT_SHIFT:
+            case LEFT_SHIFT:
+            case REMAINDER:
+            case XOR:
+                return node.getLeft().accept(this, solveLambdas);
+            default:
+                throw new UnsupportedOperationException("FOO " + node.getOperator().name());
+        }
+    }
+
+    @Override
+    public Type visit(CastExpr node, Boolean solveLambdas) {
+        return facade.convertToUsage(node.getType(), JavaParserFactory.getContext(node, typeSolver));
+    }
+
+    @Override
+    public Type visit(ClassExpr node, Boolean solveLambdas) {
+        // This implementation does not regard the actual type argument of the ClassExpr.
+        com.github.javaparser.ast.type.Type astType = node.getType();
+        Type jssType = facade.convertToUsage(astType, node.getType());
+        return new ReferenceTypeImpl(new ReflectionClassDeclaration(Class.class, typeSolver), ImmutableList.of(jssType), typeSolver);
+    }
+
+    @Override
+    public Type visit(ConditionalExpr node, Boolean solveLambdas) {
+        return node.getThenExpr().accept(this, solveLambdas);
+    }
+
+    @Override
+    public Type visit(EnclosedExpr node, Boolean solveLambdas) {
+        return node.getInner().accept(this, solveLambdas);
+    }
+
+    /**
+     * Java Parser can't differentiate between packages, internal types, and fields.
+     * All three are lumped together into FieldAccessExpr. We need to differentiate them.
+     */
+    private Type solveDotExpressionType(ReferenceTypeDeclaration parentType, FieldAccessExpr node) {
+        // Fields and internal type declarations cannot have the same name.
+        // Thus, these checks will always be mutually exclusive.
+        if (parentType.hasField(node.getName().getId())) {
+            return parentType.getField(node.getName().getId()).getType();
+        } else if (parentType.hasInternalType(node.getName().getId())) {
+            return new ReferenceTypeImpl(parentType.getInternalType(node.getName().getId()), typeSolver);
+        } else {
+            throw new UnsolvedSymbolException(node.getName().getId());
+        }
+    }
+
+    @Override
+    public Type visit(FieldAccessExpr node, Boolean solveLambdas) {
+        // We should understand if this is a static access
+        if (node.getScope() instanceof NameExpr ||
+                node.getScope() instanceof FieldAccessExpr) {
+            Expression staticValue = node.getScope();
+            SymbolReference<TypeDeclaration> typeAccessedStatically = JavaParserFactory.getContext(node, typeSolver).solveType(staticValue.toString(), typeSolver);
+            if (typeAccessedStatically.isSolved()) {
+                // TODO here maybe we have to substitute type typeParametersValues
+                return solveDotExpressionType(
+                        typeAccessedStatically.getCorrespondingDeclaration().asReferenceType(), node);
+            }
+        } else if (node.getScope()instanceof ThisExpr){
+            // If we are accessing through a 'this' expression, first resolve the type
+            // corresponding to 'this'
+            SymbolReference<TypeDeclaration> solve = facade.solve((ThisExpr) node.getScope());
+            // If found get it's declaration and get the field in there
+            if (solve.isSolved()){
+                TypeDeclaration correspondingDeclaration = solve.getCorrespondingDeclaration();
+                if (correspondingDeclaration instanceof ReferenceTypeDeclaration){
+                    return solveDotExpressionType(correspondingDeclaration.asReferenceType(), node);
+                }
+            }
+
+        } else if (node.getScope().toString().indexOf('.') > 0) {
+            // try to find fully qualified name
+            SymbolReference<ReferenceTypeDeclaration> sr = typeSolver.tryToSolveType(node.getScope().toString());
+            if (sr.isSolved()) {
+                return solveDotExpressionType(sr.getCorrespondingDeclaration(), node);
+            }
+        }
+        Optional<Value> value = null;
+        try {
+            value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getField().getId(), node);
+        } catch (UnsolvedSymbolException use) {
+            // This node may have a package name as part of its fully qualified name.
+            // We should solve for the type declaration inside this package.
+            SymbolReference<ReferenceTypeDeclaration> sref = typeSolver.tryToSolveType(node.toString());
+            if (sref.isSolved()) {
+                return new ReferenceTypeImpl(sref.getCorrespondingDeclaration(), typeSolver);
+            }
+        }
+        if (value != null && value.isPresent()) {
+            return value.get().getType();
+        } else {
+            throw new UnsolvedSymbolException(node.getField().getId());
+        }
+    }
+
+    @Override
+    public Type visit(InstanceOfExpr node, Boolean solveLambdas) {
+        return PrimitiveType.BOOLEAN;
+    }
+
+    @Override
+    public Type visit(StringLiteralExpr node, Boolean solveLambdas) {
+        return new ReferenceTypeImpl(new ReflectionTypeSolver().solveType("java.lang.String"), typeSolver);
+    }
+
+    @Override
+    public Type visit(IntegerLiteralExpr node, Boolean solveLambdas) {
+        return PrimitiveType.INT;
+    }
+
+    @Override
+    public Type visit(LongLiteralExpr node, Boolean solveLambdas) {
+        return PrimitiveType.LONG;
+    }
+
+    @Override
+    public Type visit(CharLiteralExpr node, Boolean solveLambdas) {
+        return PrimitiveType.CHAR;
+    }
+
+    @Override
+    public Type visit(DoubleLiteralExpr node, Boolean solveLambdas) {
+        if (node.getValue().toLowerCase().endsWith("f")) {
+            return PrimitiveType.FLOAT;
+        }
+        return PrimitiveType.DOUBLE;
+    }
+
+    @Override
+    public Type visit(BooleanLiteralExpr node, Boolean solveLambdas) {
+        return PrimitiveType.BOOLEAN;
+    }
+
+    @Override
+    public Type visit(NullLiteralExpr node, Boolean solveLambdas) {
+        return NullType.INSTANCE;
+    }
+
+    @Override
+    public Type visit(MethodCallExpr node, Boolean solveLambdas) {
+        logger.finest("getType on method call " + node);
+        // first solve the method
+        MethodUsage ref = facade.solveMethodAsUsage(node);
+        logger.finest("getType on method call " + node + " resolved to " + ref);
+        logger.finest("getType on method call " + node + " return type is " + ref.returnType());
+        return ref.returnType();
+        // the type is the return type of the method
+    }
+
+    @Override
+    public Type visit(NameExpr node, Boolean solveLambdas) {
+        logger.finest("getType on name expr " + node);
+        Optional<Value> value = new SymbolSolver(typeSolver).solveSymbolAsValue(node.getName().getId(), node);
+        if (!value.isPresent()) {
+            throw new UnsolvedSymbolException("Solving " + node, node.getName().getId());
+        } else {
+            return value.get().getType();
+        }
+    }
+
+    @Override
+    public Type visit(ObjectCreationExpr node, Boolean solveLambdas) {
+        Type type = facade.convertToUsage(node.getType(), node);
+        return type;
+    }
+
+    @Override
+    public Type visit(ThisExpr node, Boolean solveLambdas) {
+        // If 'this' is prefixed by a class eg. MyClass.this
+        if (node.getClassExpr().isPresent()){
+            // Get the class name
+            String className = node.getClassExpr().get().toString();
+            // Attempt to resolve using a typeSolver
+            SymbolReference<ReferenceTypeDeclaration> clazz = typeSolver.tryToSolveType(className);
+            if (clazz.isSolved()){
+                return new ReferenceTypeImpl(clazz.getCorrespondingDeclaration(),typeSolver);
+            }
+            // Attempt to resolve locally in Compilation unit
+            Optional<CompilationUnit> cu = node.getAncestorOfType(CompilationUnit.class);
+            if (cu.isPresent()){
+                Optional<ClassOrInterfaceDeclaration> classByName = cu.get().getClassByName(className);
+                if (classByName.isPresent()){
+                    return new ReferenceTypeImpl(facade.getTypeDeclaration(classByName.get()), typeSolver);
+                }
+            }
+
+        }
+        return new ReferenceTypeImpl(facade.getTypeDeclaration(facade.findContainingTypeDecl(node)), typeSolver);
+    }
+
+    @Override
+    public Type visit(SuperExpr node, Boolean solveLambdas) {
+        TypeDeclaration typeOfNode = facade.getTypeDeclaration(facade.findContainingTypeDecl(node));
+        if (typeOfNode instanceof ClassDeclaration) {
+            return ((ClassDeclaration) typeOfNode).getSuperClass();
+        } else {
+            throw new UnsupportedOperationException(node.getClass().getCanonicalName());
+        }
+    }
+
+    @Override
+    public Type visit(UnaryExpr node, Boolean solveLambdas) {
+        switch (node.getOperator()) {
+            case MINUS:
+            case PLUS:
+                return node.getExpression().accept(this, solveLambdas);
+            case LOGICAL_COMPLEMENT:
+                return PrimitiveType.BOOLEAN;
+            case POSTFIX_DECREMENT:
+            case PREFIX_DECREMENT:
+            case POSTFIX_INCREMENT:
+            case PREFIX_INCREMENT:
+                return node.getExpression().accept(this, solveLambdas);
+            default:
+                throw new UnsupportedOperationException(node.getOperator().name());
+        }
+    }
+
+    @Override
+    public Type visit(VariableDeclarationExpr node, Boolean solveLambdas) {
+        if (node.getVariables().size() != 1) {
+            throw new UnsupportedOperationException();
+        }
+        return facade.convertToUsageVariableType(node.getVariables().get(0));
+    }
+
+
+    @Override
+    public Type visit(LambdaExpr node, Boolean solveLambdas) {
+        if (getParentNode(node) instanceof MethodCallExpr) {
+            MethodCallExpr callExpr = (MethodCallExpr) getParentNode(node);
+            int pos = JavaParserSymbolDeclaration.getParamPos(node);
+            SymbolReference<MethodDeclaration> refMethod = facade.solve(callExpr);
+            if (!refMethod.isSolved()) {
+                throw new UnsolvedSymbolException(getParentNode(node).toString(), callExpr.getName().getId());
+            }
+            logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName());
+            if (solveLambdas) {
+
+                // The type parameter referred here should be the java.util.stream.Stream.T
+                Type result = refMethod.getCorrespondingDeclaration().getParam(pos).getType();
+
+                if (callExpr.getScope().isPresent()) {
+                    Expression scope = callExpr.getScope().get();
+
+                    // If it is a static call we should not try to get the type of the scope
+                    boolean staticCall = false;
+                    if (scope instanceof NameExpr) {
+                        NameExpr nameExpr = (NameExpr) scope;
+                        try {
+                            SymbolReference<TypeDeclaration> type = JavaParserFactory.getContext(nameExpr, typeSolver).solveType(nameExpr.getName().getId(), typeSolver);
+                            if (type.isSolved()){
+                                staticCall = true;
+                            }
+                        } catch (Exception e) {
+
+                        }
+                    }
+
+                    if (!staticCall) {
+                        Type scopeType = facade.getType(scope);
+                        if (scopeType.isReferenceType()) {
+                            result = scopeType.asReferenceType().useThisTypeParametersOnTheGivenType(result);
+                        }
+                    }
+                }
+
+                // We need to replace the type variables
+                Context ctx = JavaParserFactory.getContext(node, typeSolver);
+                result = facade.solveGenericTypes(result, ctx, typeSolver);
+
+                //We should find out which is the functional method (e.g., apply) and replace the params of the
+                //solveLambdas with it, to derive so the values. We should also consider the value returned by the
+                //lambdas
+                Optional<MethodUsage> functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(result);
+                if (functionalMethod.isPresent()) {
+                    LambdaExpr lambdaExpr = node;
+
+                    InferenceContext lambdaCtx = new InferenceContext(MyObjectProvider.INSTANCE);
+                    InferenceContext funcInterfaceCtx = new InferenceContext(MyObjectProvider.INSTANCE);
+
+                    // At this point parameterType
+                    // if Function<T=? super Stream.T, ? extends map.R>
+                    // we should replace Stream.T
+                    Type functionalInterfaceType = ReferenceTypeImpl.undeterminedParameters(functionalMethod.get().getDeclaration().declaringType(), typeSolver);
+
+                    lambdaCtx.addPair(result, functionalInterfaceType);
+
+                    Type actualType;
+
+                    if (lambdaExpr.getBody() instanceof ExpressionStmt) {
+                        actualType = facade.getType(((ExpressionStmt)lambdaExpr.getBody()).getExpression());
+                    } else if (lambdaExpr.getBody() instanceof BlockStmt) {
+                        BlockStmt blockStmt = (BlockStmt) lambdaExpr.getBody();
+                        NodeList<Statement> statements = blockStmt.getStatements();
+
+                        // Get all the return statements in the lambda block
+                        List<ReturnStmt> returnStmts = blockStmt.getNodesByType(ReturnStmt.class);
+
+                        if (returnStmts.size() > 0){
+
+                            actualType = returnStmts.stream()
+                            .map(returnStmt -> {
+                                Optional<Expression> expression = returnStmt.getExpression();
+                                if (expression.isPresent()){
+                                    return facade.getType(expression.get());
+                                } else{
+                                    return VoidType.INSTANCE;
+                                }
+                            })
+                            .filter(x -> x != null && !x.isVoid() && !x.isNull())
+                            .findFirst()
+                            .orElse(VoidType.INSTANCE);
+
+                        } else {
+                            return VoidType.INSTANCE;
+                        }
+
+
+                    } else {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    Type formalType = functionalMethod.get().returnType();
+
+                    // Infer the functional interfaces' return vs actual type
+                    funcInterfaceCtx.addPair(formalType, actualType);
+                    // Substitute to obtain a new type
+                    Type functionalTypeWithReturn = funcInterfaceCtx.resolve(funcInterfaceCtx.addSingle(functionalInterfaceType));
+
+                    // if the functional method returns void anyway
+                    // we don't need to bother inferring types
+                    if (!(formalType instanceof VoidType)){
+                        lambdaCtx.addPair(result, functionalTypeWithReturn);
+                        result = lambdaCtx.resolve(lambdaCtx.addSingle(result));
+                    }
+                }
+
+                return result;
+            } else {
+                return refMethod.getCorrespondingDeclaration().getParam(pos).getType();
+            }
+        } else {
+            throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value");
+        }
+    }
+
+    @Override
+    public Type visit(MethodReferenceExpr node, Boolean solveLambdas) {
+        if (getParentNode(node) instanceof MethodCallExpr) {
+            MethodCallExpr callExpr = (MethodCallExpr) getParentNode(node);
+            int pos = JavaParserSymbolDeclaration.getParamPos(node);
+            SymbolReference<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration> refMethod = facade.solve(callExpr, false);
+            if (!refMethod.isSolved()) {
+                throw new UnsolvedSymbolException(getParentNode(node).toString(), callExpr.getName().getId());
+            }
+            logger.finest("getType on method reference expr " + refMethod.getCorrespondingDeclaration().getName());
+            //logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos));
+            if (solveLambdas) {
+                MethodUsage usage = facade.solveMethodAsUsage(callExpr);
+                Type result = usage.getParamType(pos);
+                // We need to replace the type variables
+                Context ctx = JavaParserFactory.getContext(node, typeSolver);
+                result = facade.solveGenericTypes(result, ctx, typeSolver);
+
+                //We should find out which is the functional method (e.g., apply) and replace the params of the
+                //solveLambdas with it, to derive so the values. We should also consider the value returned by the
+                //lambdas
+                Optional<MethodUsage> functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(result);
+                if (functionalMethod.isPresent()) {
+                    if (node instanceof MethodReferenceExpr) {
+                        MethodReferenceExpr methodReferenceExpr = (MethodReferenceExpr) node;
+
+                        Type actualType = facade.toMethodUsage(methodReferenceExpr).returnType();
+                        Type formalType = functionalMethod.get().returnType();
+
+                        InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE);
+                        inferenceContext.addPair(formalType, actualType);
+                        result = inferenceContext.resolve(inferenceContext.addSingle(result));
+                    }
+                }
+
+                return result;
+            } else {
+                return refMethod.getCorrespondingDeclaration().getParam(pos).getType();
+            }
+        } else {
+            throw new UnsupportedOperationException("The type of a method reference expr depends on the position and its return value");
+        }
+    }
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java
new file mode 100644
index 0000000..21dcf7c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/UnsolvedSymbolException.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+/**
+ * @author Federico Tomassetti
+ *
+ * @deprecated Use {@link com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException} instead
+ */
+// Use the one in model instead
+@Deprecated
+public class UnsolvedSymbolException extends RuntimeException {
+
+    private String context;
+    private String name;
+    private TypeSolver typeSolver;
+
+    public UnsolvedSymbolException(String name, TypeSolver typeSolver) {
+        super("Unsolved symbol : " + name + " using typesolver " + typeSolver);
+        this.typeSolver = typeSolver;
+        this.name = name;
+    }
+
+    public UnsolvedSymbolException(Context context, String name) {
+        super("Unsolved symbol in " + context + " : " + name);
+        this.context = context.toString();
+        this.name = name;
+    }
+
+    public UnsolvedSymbolException(String context, String name) {
+        super("Unsolved symbol in " + context + " : " + name);
+        this.context = context;
+        this.name = name;
+    }
+
+    public UnsolvedSymbolException(String name) {
+        super("Unsolved symbol : " + name);
+        this.context = "unknown";
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return "UnsolvedSymbolException{" +
+                "context='" + context + '\'' +
+                ", name='" + name + '\'' +
+                ", typeSolver=" + typeSolver +
+                '}';
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java
new file mode 100644
index 0000000..e08bfb0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+import java.util.Optional;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public abstract class AbstractJavaParserContext<N extends Node> implements Context {
+
+    protected N wrappedNode;
+    protected TypeSolver typeSolver;
+
+    ///
+    /// Static methods
+    ///
+
+    public static final SymbolReference<ValueDeclaration> solveWith(SymbolDeclarator symbolDeclarator, String name) {
+        for (ValueDeclaration decl : symbolDeclarator.getSymbolDeclarations()) {
+            if (decl.getName().equals(name)) {
+                return SymbolReference.solved(decl);
+            }
+        }
+        return SymbolReference.unsolved(ValueDeclaration.class);
+    }
+
+    ///
+    /// Constructors
+    ///
+
+    public AbstractJavaParserContext(N wrappedNode, TypeSolver typeSolver) {
+        if (wrappedNode == null) {
+            throw new NullPointerException();
+        }
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        AbstractJavaParserContext<?> that = (AbstractJavaParserContext<?>) o;
+
+        if (wrappedNode != null ? !wrappedNode.equals(that.wrappedNode) : that.wrappedNode != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return wrappedNode != null ? wrappedNode.hashCode() : 0;
+    }
+
+    @Override
+    public Optional<Type> solveGenericType(String name, TypeSolver typeSolver) {
+        Context parent = getParent();
+        if (parent == null) {
+            return Optional.empty();
+        } else {
+            return parent.solveGenericType(name, typeSolver);
+        }
+    }
+
+    @Override
+    public final Context getParent() {
+        if (getParentNode(wrappedNode) instanceof MethodCallExpr) {
+            MethodCallExpr parentCall = (MethodCallExpr) getParentNode(wrappedNode);
+            boolean found = false;
+            if (parentCall.getArguments() != null) {
+                for (Expression expression : parentCall.getArguments()) {
+                    if (expression == wrappedNode) {
+                        found = true;
+                    }
+                }
+            }
+            if (found) {
+                Node notMethod = getParentNode(wrappedNode);
+                while (notMethod instanceof MethodCallExpr) {
+                    notMethod = getParentNode(notMethod);
+                }
+                return JavaParserFactory.getContext(notMethod, typeSolver);
+            }
+        }
+        Node notMethod = getParentNode(wrappedNode);
+        while (notMethod instanceof MethodCallExpr || notMethod instanceof FieldAccessExpr) {
+            notMethod = getParentNode(notMethod);
+        }
+        return JavaParserFactory.getContext(notMethod, typeSolver);
+    }
+
+    ///
+    /// Protected methods
+    ///
+
+    protected Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) {
+        return symbolDeclarator.getSymbolDeclarations().stream()
+                .filter(d -> d.getName().equals(name))
+                .map(d -> Value.from(d))
+                .findFirst();
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java
new file mode 100644
index 0000000..7a93633
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractMethodLikeDeclarationContext.java
@@ -0,0 +1,101 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.nodeTypes.NodeWithParameters;
+import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public abstract class AbstractMethodLikeDeclarationContext
+        <T extends Node & NodeWithParameters<T> & NodeWithTypeParameters<T>> extends AbstractJavaParserContext<T> {
+
+    public AbstractMethodLikeDeclarationContext(T wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    public final SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (Parameter parameter : wrappedNode.getParameters()) {
+            SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
+            SymbolReference<? extends ValueDeclaration> symbolReference = AbstractJavaParserContext.solveWith(sb, name);
+            if (symbolReference.isSolved()) {
+                return symbolReference;
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public final Optional<Type> solveGenericType(String name, TypeSolver typeSolver) {
+        for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) {
+            if (tp.getName().getId().equals(name)) {
+                return Optional.of(new TypeVariable(new JavaParserTypeParameter(tp, typeSolver)));
+            }
+        }
+        return super.solveGenericType(name, typeSolver);
+    }
+
+    @Override
+    public final Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        for (Parameter parameter : wrappedNode.getParameters()) {
+            SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
+            Optional<Value> symbolReference = solveWithAsValue(sb, name, typeSolver);
+            if (symbolReference.isPresent()) {
+                // Perform parameter type substitution as needed
+                return symbolReference;
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        return getParent().solveSymbolAsValue(name, typeSolver);
+    }
+
+    @Override
+    public final SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        if (wrappedNode.getTypeParameters() != null) {
+            for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) {
+                if (tp.getName().getId().equals(name)) {
+                    return SymbolReference.solved(new JavaParserTypeParameter(tp, typeSolver));
+                }
+            }
+        }
+        
+        // Local types
+        List<com.github.javaparser.ast.body.TypeDeclaration> localTypes = wrappedNode.getChildNodesByType(
+                com.github.javaparser.ast.body.TypeDeclaration.class);
+        for (com.github.javaparser.ast.body.TypeDeclaration<?> localType : localTypes) {
+            if (localType.getName().getId().equals(name)) {
+                return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(localType));
+            } else if (name.startsWith(String.format("%s.", localType.getName()))) {
+                return JavaParserFactory.getContext(localType, typeSolver).solveType(
+                        name.substring(localType.getName().getId().length() + 1), typeSolver);
+            }
+        }
+        
+        return getParent().solveType(name, typeSolver);
+    }
+
+    @Override
+    public final SymbolReference<MethodDeclaration> solveMethod(
+            String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java
new file mode 100644
index 0000000..3eef0c9
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AnonymousClassDeclarationContext.java
@@ -0,0 +1,186 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations
+    .JavaParserAnonymousClassDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import com.google.common.base.Preconditions;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * A symbol resolution context for an object creation node.
+ */
+public class AnonymousClassDeclarationContext extends AbstractJavaParserContext<ObjectCreationExpr> {
+
+  private final JavaParserAnonymousClassDeclaration myDeclaration =
+      new JavaParserAnonymousClassDeclaration(wrappedNode, typeSolver);
+
+  public AnonymousClassDeclarationContext(ObjectCreationExpr node, TypeSolver typeSolver) {
+    super(node, typeSolver);
+    Preconditions.checkArgument(node.getAnonymousClassBody().isPresent(),
+                                "An anonymous class must have a body");
+  }
+
+  @Override
+  public SymbolReference<MethodDeclaration> solveMethod(String name,
+                                                        List<Type> argumentsTypes,
+                                                        boolean staticOnly,
+                                                        TypeSolver typeSolver) {
+    List<MethodDeclaration> candidateMethods =
+        myDeclaration
+            .getDeclaredMethods()
+            .stream()
+            .filter(m -> m.getName().equals(name) && (!staticOnly || m.isStatic()))
+            .collect(Collectors.toList());
+
+    if (!Object.class.getCanonicalName().equals(myDeclaration.getQualifiedName())) {
+      for (ReferenceType ancestor : myDeclaration.getAncestors()) {
+        SymbolReference<MethodDeclaration> res =
+            MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(),
+                                                    name,
+                                                    argumentsTypes,
+                                                    staticOnly,
+                                                    typeSolver);
+        // consider methods from superclasses and only default methods from interfaces :
+        // not true, we should keep abstract as a valid candidate
+        // abstract are removed in MethodResolutionLogic.isApplicable is necessary
+        if (res.isSolved()) {
+          candidateMethods.add(res.getCorrespondingDeclaration());
+        }
+      }
+    }
+
+    // We want to avoid infinite recursion when a class is using its own method
+    // see issue #75
+    if (candidateMethods.isEmpty()) {
+      SymbolReference<MethodDeclaration> parentSolution =
+          getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+      if (parentSolution.isSolved()) {
+        candidateMethods.add(parentSolution.getCorrespondingDeclaration());
+      }
+    }
+
+    // if is interface and candidate method list is empty, we should check the Object Methods
+    if (candidateMethods.isEmpty() && myDeclaration.getSuperTypeDeclaration().isInterface()) {
+      SymbolReference<MethodDeclaration> res =
+          MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class,
+                                                                                 typeSolver),
+                                                  name,
+                                                  argumentsTypes,
+                                                  false,
+                                                  typeSolver);
+      if (res.isSolved()) {
+        candidateMethods.add(res.getCorrespondingDeclaration());
+      }
+    }
+
+    return MethodResolutionLogic.findMostApplicable(candidateMethods,
+                                                    name,
+                                                    argumentsTypes,
+                                                    typeSolver);
+  }
+
+  @Override
+  public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+    List<com.github.javaparser.ast.body.TypeDeclaration> typeDeclarations =
+        myDeclaration
+            .findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class);
+
+    Optional<SymbolReference<TypeDeclaration>> exactMatch =
+        typeDeclarations
+            .stream()
+            .filter(internalType -> internalType.getName().getId().equals(name))
+            .findFirst()
+            .map(internalType ->
+                     SymbolReference.solved(
+                         JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType)));
+
+    if(exactMatch.isPresent()){
+      return exactMatch.get();
+    }
+
+    Optional<SymbolReference<TypeDeclaration>> recursiveMatch =
+        typeDeclarations
+            .stream()
+            .filter(internalType -> name.startsWith(String.format("%s.", internalType.getName())))
+            .findFirst()
+            .map(internalType ->
+                     JavaParserFactory
+                         .getContext(internalType, typeSolver)
+                         .solveType(name.substring(internalType.getName().getId().length() + 1),
+                                    typeSolver));
+
+    if (recursiveMatch.isPresent()) {
+      return recursiveMatch.get();
+    }
+
+    Optional<SymbolReference<TypeDeclaration>> typeArgumentsMatch =
+        wrappedNode
+            .getTypeArguments()
+            .map(nodes ->
+                     ((NodeWithTypeArguments<?>) nodes).getTypeArguments()
+                                                       .orElse(new NodeList<>()))
+            .orElse(new NodeList<>())
+            .stream()
+            .filter(type -> type.toString().equals(name))
+            .findFirst()
+            .map(matchingType ->
+                     SymbolReference.solved(
+                         new JavaParserTypeParameter(new TypeParameter(matchingType.toString()),
+                                                     typeSolver)));
+
+    if (typeArgumentsMatch.isPresent()) {
+      return typeArgumentsMatch.get();
+    }
+
+    // Look into extended classes and implemented interfaces
+    for (ReferenceType ancestor : myDeclaration.getAncestors()) {
+      // look at names of extended classes and implemented interfaces (this may not be important because they are checked in CompilationUnitContext)
+      if (ancestor.getTypeDeclaration().getName().equals(name)) {
+        return SymbolReference.solved(ancestor.getTypeDeclaration());
+      } 
+      // look into internal types of extended classes and implemented interfaces
+      try {
+        for (TypeDeclaration internalTypeDeclaration : ancestor.getTypeDeclaration().internalTypes()) {
+          if (internalTypeDeclaration.getName().equals(name)) {
+            return SymbolReference.solved(internalTypeDeclaration);
+          }
+        }
+      } catch (UnsupportedOperationException e) {
+        // just continue using the next ancestor
+      }
+    }
+    
+    return getParent().solveType(name, typeSolver);
+  }
+
+  @Override
+  public SymbolReference<? extends ValueDeclaration> solveSymbol(String name,
+                                                                 TypeSolver typeSolver) {
+    Preconditions.checkArgument(typeSolver != null);
+
+    if (myDeclaration.hasVisibleField(name)) {
+      return SymbolReference.solved(myDeclaration.getVisibleField(name));
+    }
+
+    return getParent().solveSymbol(name, typeSolver);
+  }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java
new file mode 100644
index 0000000..e9ce5d7
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CatchClauseContext.java
@@ -0,0 +1,54 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.stmt.CatchClause;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Fred Lefévère-Laoide
+ */
+public class CatchClauseContext extends AbstractJavaParserContext<CatchClause> {
+
+    public CatchClauseContext(CatchClause wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    public final SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(wrappedNode.getParameter(), typeSolver);
+        SymbolReference<? extends ValueDeclaration> symbolReference = AbstractJavaParserContext.solveWith(sb, name);
+        if (symbolReference.isSolved()) {
+            return symbolReference;
+        }
+
+        // if nothing is found we should ask the parent context
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public final Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(wrappedNode.getParameter(), typeSolver);
+        Optional<Value> symbolReference = solveWithAsValue(sb, name, typeSolver);
+        if (symbolReference.isPresent()) {
+            // Perform parameter type substitution as needed
+            return symbolReference;
+        }
+
+        // if nothing is found we should ask the parent context
+        return getParent().solveSymbolAsValue(name, typeSolver);
+    }
+
+    @Override
+    public final SymbolReference<MethodDeclaration> solveMethod(
+            String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java
new file mode 100644
index 0000000..a805bf4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ClassOrInterfaceDeclarationContext.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ClassOrInterfaceDeclarationContext extends AbstractJavaParserContext<ClassOrInterfaceDeclaration> {
+
+    private JavaParserTypeDeclarationAdapter javaParserTypeDeclarationAdapter;
+
+    ///
+    /// Constructors
+    ///
+
+    public ClassOrInterfaceDeclarationContext(ClassOrInterfaceDeclaration wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+        this.javaParserTypeDeclarationAdapter = new JavaParserTypeDeclarationAdapter(wrappedNode, typeSolver,
+                getDeclaration(), this);
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        if (typeSolver == null) throw new IllegalArgumentException();
+
+        if (this.getDeclaration().hasVisibleField(name)) {
+            return SymbolReference.solved(this.getDeclaration().getVisibleField(name));
+        }
+
+        // then to parent
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        if (typeSolver == null) throw new IllegalArgumentException();
+
+        if (this.getDeclaration().hasVisibleField(name)) {
+            return Optional.of(Value.from(this.getDeclaration().getVisibleField(name)));
+        }
+
+        // then to parent
+        return getParent().solveSymbolAsValue(name, typeSolver);
+    }
+
+    @Override
+    public Optional<Type> solveGenericType(String name, TypeSolver typeSolver) {
+        for (com.github.javaparser.ast.type.TypeParameter tp : wrappedNode.getTypeParameters()) {
+            if (tp.getName().getId().equals(name)) {
+                return Optional.of(new TypeVariable(new JavaParserTypeParameter(tp, typeSolver)));
+            }
+        }
+        return getParent().solveGenericType(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        return javaParserTypeDeclarationAdapter.solveType(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+    }
+
+    public SymbolReference<ConstructorDeclaration> solveConstructor(List<Type> argumentsTypes, TypeSolver typeSolver) {
+        return javaParserTypeDeclarationAdapter.solveConstructor(argumentsTypes, typeSolver);
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private ReferenceTypeDeclaration getDeclaration() {
+        return JavaParserFacade.get(typeSolver).getTypeDeclaration(this.wrappedNode);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
new file mode 100644
index 0000000..d7c92b9
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.ImportDeclaration;
+import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.TypeDeclaration;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.Name;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnnotationDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class CompilationUnitContext extends AbstractJavaParserContext<CompilationUnit> {
+
+    ///
+    /// Static methods
+    ///
+
+    private static boolean isQualifiedName(String name) {
+        return name.contains(".");
+    }
+
+    ///
+    /// Constructors
+    ///
+
+    public CompilationUnitContext(CompilationUnit wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+
+        // solve absolute references
+        String itName = name;
+        while (itName.contains(".")) {
+            String typeName = getType(itName);
+            String memberName = getMember(itName);
+            SymbolReference<com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration> type = this.solveType(typeName, typeSolver);
+            if (type.isSolved()) {
+                return new SymbolSolver(typeSolver).solveSymbolInType(type.getCorrespondingDeclaration(), memberName);
+            } else {
+                itName = typeName;
+            }
+        }
+
+        // Look among statically imported values
+        if (wrappedNode.getImports() != null) {
+            for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+                if(importDecl.isStatic()){
+                    if(importDecl.isAsterisk()) {
+                        String qName = importDecl.getNameAsString();
+                        com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration importedType = typeSolver.solveType(qName);
+                        SymbolReference<? extends ValueDeclaration> ref = new SymbolSolver(typeSolver).solveSymbolInType(importedType, name);
+                        if (ref.isSolved()) {
+                            return ref;
+                        }
+                    } else{
+                        String whole = importDecl.getNameAsString();
+
+                        // split in field/method name and type name
+                        String memberName = getMember(whole);
+                        String typeName = getType(whole);
+
+                        if (memberName.equals(name)) {
+                            com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration importedType = typeSolver.solveType(typeName);
+                            return new SymbolSolver(typeSolver).solveSymbolInType(importedType, memberName);
+                        }
+                    }
+                }
+            }
+        }
+
+        return SymbolReference.unsolved(ValueDeclaration.class);
+    }
+
+    @Override
+    public SymbolReference<com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        if (wrappedNode.getTypes() != null) {
+            for (TypeDeclaration<?> type : wrappedNode.getTypes()) {
+                if (type.getName().getId().equals(name)) {
+                    if (type instanceof ClassOrInterfaceDeclaration) {
+                        return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration) type));
+                    } else if (type instanceof AnnotationDeclaration) {
+                        return SymbolReference.solved(new JavaParserAnnotationDeclaration((AnnotationDeclaration) type, typeSolver));
+                    } else {
+                        throw new UnsupportedOperationException(type.getClass().getCanonicalName());
+                    }
+                }
+            }
+        }
+
+        if (wrappedNode.getImports() != null) {
+            int dotPos = name.indexOf('.');
+            String prefix = null;
+            if (dotPos > -1) {
+                prefix = name.substring(0, dotPos);
+            }
+            // look into type imports
+            for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+                if (!importDecl.isAsterisk()) {
+                    String qName = importDecl.getNameAsString();
+                    boolean defaultPackage = !importDecl.getName().getQualifier().isPresent();
+                    boolean found = !defaultPackage && importDecl.getName().getIdentifier().equals(name);
+                    if (!found) {
+                        if (prefix != null) {
+                            found = qName.endsWith("." + prefix);
+                            if (found) {
+                                qName = qName + name.substring(dotPos);
+                            }
+                        }
+                    }
+                    if (found) {
+                        SymbolReference<com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+                        if (ref.isSolved()) {
+                            return SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class);
+                        }
+                    }
+                }
+            }
+            // look into type imports on demand
+            for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+                if (importDecl.isAsterisk()) {
+                    String qName = importDecl.getNameAsString() + "." + name;
+                    SymbolReference<com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+                    if (ref.isSolved()) {
+                        return SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class);
+                    }
+                }
+            }
+        }
+
+        // Look in current package
+        if (this.wrappedNode.getPackageDeclaration().isPresent()) {
+            String qName = this.wrappedNode.getPackageDeclaration().get().getName().toString() + "." + name;
+            SymbolReference<com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+            if (ref.isSolved()) {
+                return SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class);
+            }
+        } else {
+            // look for classes in the default package
+            String qName = name;
+            SymbolReference<com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
+            if (ref.isSolved()) {
+                return SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class);
+            }
+        }
+
+        // Look in the java.lang package
+        SymbolReference<com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration> ref = typeSolver.tryToSolveType("java.lang." + name);
+        if (ref.isSolved()) {
+            return SymbolReference.adapt(ref, com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class);
+        }
+
+        // DO NOT look for absolute name if this name is not qualified: you cannot import classes from the default package
+        if (isQualifiedName(name)) {
+            return SymbolReference.adapt(typeSolver.tryToSolveType(name), com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.class);
+        } else {
+            return SymbolReference.unsolved(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration.class);
+        }
+    }
+
+    private String qName(ClassOrInterfaceType type) {
+        if (type.getScope().isPresent()) {
+            return qName(type.getScope().get()) + "." + type.getName().getId();
+        } else {
+            return type.getName().getId();
+        }
+    }
+
+    private String qName(Name name) {
+        if (name.getQualifier().isPresent()) {
+            return qName(name.getQualifier().get()) + "." + name.getId();
+        } else {
+            return name.getId();
+        }
+    }
+
+    private String toSimpleName(String qName) {
+        String[] parts = qName.split("\\.");
+        return parts[parts.length - 1];
+    }
+
+    private String packageName(String qName) {
+        int lastDot = qName.lastIndexOf('.');
+        if (lastDot == -1) {
+            throw new UnsupportedOperationException();
+        } else {
+            return qName.substring(0, lastDot);
+        }
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        for (ImportDeclaration importDecl : wrappedNode.getImports()) {
+            if(importDecl.isStatic()){
+                if(importDecl.isAsterisk()){
+                    String importString = importDecl.getNameAsString();
+
+                    if (this.wrappedNode.getPackageDeclaration().isPresent()
+                            && this.wrappedNode.getPackageDeclaration().get().getName().getIdentifier().equals(packageName(importString))
+                            && this.wrappedNode.getTypes().stream().anyMatch(it -> it.getName().getIdentifier().equals(toSimpleName(importString)))) {
+                        // We are using a static import on a type defined in this file. It means the value was not found at
+                        // a lower level so this will fail
+                        return SymbolReference.unsolved(MethodDeclaration.class);
+                    }
+
+                    com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration ref = typeSolver.solveType(importString);
+                    SymbolReference<MethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver);
+
+                    if (method.isSolved()) {
+                        return method;
+                    }
+                } else{
+                    String qName = importDecl.getNameAsString();
+
+                    if (qName.equals(name) || qName.endsWith("." + name)) {
+                        String typeName = getType(qName);
+                        com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration ref = typeSolver.solveType(typeName);
+                        SymbolReference<MethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true, typeSolver);
+                        if (method.isSolved()) {
+                            return method;
+                        }
+                    }
+                }
+            }
+        }
+        return SymbolReference.unsolved(MethodDeclaration.class);
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private String getType(String qName) {
+        int index = qName.lastIndexOf('.');
+        if (index == -1) {
+            throw new UnsupportedOperationException();
+        }
+        String typeName = qName.substring(0, index);
+        return typeName;
+    }
+
+    private String getMember(String qName) {
+        int index = qName.lastIndexOf('.');
+        if (index == -1) {
+            throw new UnsupportedOperationException();
+        }
+        String memberName = qName.substring(index + 1);
+        return memberName;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java
new file mode 100644
index 0000000..bebaa73
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ConstructorContext.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ConstructorContext extends AbstractMethodLikeDeclarationContext<ConstructorDeclaration> {
+
+    ///
+    /// Constructors
+    ///
+
+    public ConstructorContext(ConstructorDeclaration wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java
new file mode 100644
index 0000000..e4b791d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ContextHelper.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistEnumDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionEnumDeclaration;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ContextHelper {
+
+    private ContextHelper() {
+        // prevent instantiation
+    }
+
+    public static Optional<MethodUsage> solveMethodAsUsage(TypeDeclaration typeDeclaration, String name,
+                                                           List<Type> argumentsTypes, TypeSolver typeSolver,
+                                                           Context invokationContext, List<Type> typeParameters) {
+        if (typeDeclaration instanceof JavassistClassDeclaration) {
+            return ((JavassistClassDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
+        } else if (typeDeclaration instanceof JavassistInterfaceDeclaration) {
+            return ((JavassistInterfaceDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
+        } else if (typeDeclaration instanceof JavassistEnumDeclaration) {
+            return ((JavassistEnumDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
+        } else if (typeDeclaration instanceof ReflectionClassDeclaration) {
+            return ((ReflectionClassDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
+        } else if (typeDeclaration instanceof ReflectionInterfaceDeclaration) {
+            return ((ReflectionInterfaceDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
+        } else if (typeDeclaration instanceof ReflectionEnumDeclaration) {
+            return ((ReflectionEnumDeclaration) typeDeclaration).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, typeParameters);
+        } else if (typeDeclaration instanceof JavaParserClassDeclaration) {
+            return ((JavaParserClassDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver);
+        } else if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
+            return ((JavaParserInterfaceDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver);
+        } else if (typeDeclaration instanceof JavaParserEnumDeclaration) {
+            return ((JavaParserEnumDeclaration) typeDeclaration).getContext().solveMethodAsUsage(name, argumentsTypes, typeSolver);
+        }
+        throw new UnsupportedOperationException(typeDeclaration.toString());
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java
new file mode 100644
index 0000000..8e40586
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/EnumDeclarationContext.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumConstantDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class EnumDeclarationContext extends AbstractJavaParserContext<EnumDeclaration> {
+
+    private JavaParserTypeDeclarationAdapter javaParserTypeDeclarationAdapter;
+
+    public EnumDeclarationContext(EnumDeclaration wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+        this.javaParserTypeDeclarationAdapter = new JavaParserTypeDeclarationAdapter(wrappedNode, typeSolver,
+                getDeclaration(), this);
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        if (typeSolver == null) throw new IllegalArgumentException();
+
+        // among constants
+        for (EnumConstantDeclaration constant : wrappedNode.getEntries()) {
+            if (constant.getName().getId().equals(name)) {
+                return SymbolReference.solved(new JavaParserEnumConstantDeclaration(constant, typeSolver));
+            }
+        }
+
+        if (this.getDeclaration().hasField(name)) {
+            return SymbolReference.solved(this.getDeclaration().getField(name));
+        }
+
+        // then to parent
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        return javaParserTypeDeclarationAdapter.solveType(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return javaParserTypeDeclarationAdapter.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private ReferenceTypeDeclaration getDeclaration() {
+        return new JavaParserEnumDeclaration(this.wrappedNode, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java
new file mode 100644
index 0000000..85b3048
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
+import com.github.javaparser.ast.expr.ThisExpr;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.PrimitiveType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class FieldAccessContext extends AbstractJavaParserContext<FieldAccessExpr> {
+
+    private static final String ARRAY_LENGTH_FIELD_NAME = "length";
+
+    public FieldAccessContext(FieldAccessExpr wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        if (wrappedNode.getField().toString().equals(name)) {
+            if (wrappedNode.getScope() instanceof ThisExpr) {
+                Type typeOfThis = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode);
+                return new SymbolSolver(typeSolver).solveSymbolInType(typeOfThis.asReferenceType().getTypeDeclaration(), name);
+            }
+        }
+        return JavaParserFactory.getContext(getParentNode(wrappedNode), typeSolver).solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        return JavaParserFactory.getContext(getParentNode(wrappedNode), typeSolver).solveType(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return JavaParserFactory.getContext(getParentNode(wrappedNode), typeSolver).solveMethod(name, parameterTypes, false, typeSolver);
+    }
+
+    @Override
+    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        Expression scope = wrappedNode.getScope();
+        if (wrappedNode.getField().toString().equals(name)) {
+            Type typeOfScope = JavaParserFacade.get(typeSolver).getType(scope);
+            if (typeOfScope.isArray() && name.equals(ARRAY_LENGTH_FIELD_NAME)) {
+                return Optional.of(new Value(PrimitiveType.INT, ARRAY_LENGTH_FIELD_NAME));
+            }
+            if (typeOfScope.isReferenceType()) {
+                Optional<Type> typeUsage = typeOfScope.asReferenceType().getFieldType(name);
+                if (typeUsage.isPresent()) {
+                    return Optional.of(new Value(typeUsage.get(), name));
+                } else {
+                    return Optional.empty();
+                }
+            } else {
+                return Optional.empty();
+            }
+        } else {
+            return getParent().solveSymbolAsValue(name, typeSolver);
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java
new file mode 100644
index 0000000..e6a17e4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.AssignExpr;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.nodeTypes.NodeWithStatements;
+import com.github.javaparser.ast.stmt.ForStmt;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.List;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+public class ForStatementContext extends AbstractJavaParserContext<ForStmt> {
+
+    public ForStatementContext(ForStmt wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (Expression expression : wrappedNode.getInitialization()) {
+            if (expression instanceof VariableDeclarationExpr) {
+                VariableDeclarationExpr variableDeclarationExpr = (VariableDeclarationExpr) expression;
+                for (VariableDeclarator variableDeclarator : variableDeclarationExpr.getVariables()) {
+                    if (variableDeclarator.getName().getId().equals(name)) {
+                        return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver));
+                    }
+                }
+            } else if (!(expression instanceof AssignExpr || expression instanceof MethodCallExpr)) {
+                throw new UnsupportedOperationException(expression.getClass().getCanonicalName());
+            }
+        }
+
+        if (getParentNode(wrappedNode) instanceof NodeWithStatements) {
+            return StatementContext.solveInBlock(name, typeSolver, wrappedNode);
+        } else {
+            return getParent().solveSymbol(name, typeSolver);
+        }
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java
new file mode 100644
index 0000000..35df8ba
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForechStatementContext.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.ForeachStmt;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.List;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+public class ForechStatementContext extends AbstractJavaParserContext<ForeachStmt> {
+
+    public ForechStatementContext(ForeachStmt wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        if (wrappedNode.getVariable().getVariables().size() != 1) {
+            throw new IllegalStateException();
+        }
+        VariableDeclarator variableDeclarator = wrappedNode.getVariable().getVariables().get(0);
+        if (variableDeclarator.getName().getId().equals(name)) {
+            return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver));
+        } else {
+            if (getParentNode(wrappedNode) instanceof BlockStmt) {
+                return StatementContext.solveInBlock(name, typeSolver, wrappedNode);
+            } else {
+                return getParent().solveSymbol(name, typeSolver);
+            }
+        }
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
new file mode 100644
index 0000000..65e4b5a
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/JavaParserTypeDeclarationAdapter.java
@@ -0,0 +1,133 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
+import com.github.javaparser.symbolsolver.resolution.ConstructorResolutionLogic;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserTypeDeclarationAdapter {
+
+    private com.github.javaparser.ast.body.TypeDeclaration<?> wrappedNode;
+    private TypeSolver typeSolver;
+    private Context context;
+    private ReferenceTypeDeclaration typeDeclaration;
+
+    public JavaParserTypeDeclarationAdapter(com.github.javaparser.ast.body.TypeDeclaration<?> wrappedNode, TypeSolver typeSolver,
+                                            ReferenceTypeDeclaration typeDeclaration,
+                                            Context context) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+        this.typeDeclaration = typeDeclaration;
+        this.context = context;
+    }
+
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        if (this.wrappedNode.getName().getId().equals(name)) {
+            return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(wrappedNode));
+        }
+
+        // Internal classes
+        for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
+                com.github.javaparser.ast.body.TypeDeclaration<?> internalType = (com.github.javaparser.ast.body.TypeDeclaration<?>) member;
+                if (internalType.getName().getId().equals(name)) {
+                    return SymbolReference.solved(JavaParserFacade.get(typeSolver).getTypeDeclaration(internalType));
+                } else if (name.startsWith(String.format("%s.%s", wrappedNode.getName(), internalType.getName()))) {
+                    return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(wrappedNode.getName().getId().length() + 1), typeSolver);
+                } else if (name.startsWith(String.format("%s.", internalType.getName()))) {
+                    return JavaParserFactory.getContext(internalType, typeSolver).solveType(name.substring(internalType.getName().getId().length() + 1), typeSolver);
+                }
+            }
+        }
+
+        if (wrappedNode instanceof NodeWithTypeParameters) {
+            NodeWithTypeParameters<?> nodeWithTypeParameters = (NodeWithTypeParameters<?>) wrappedNode;
+            for (TypeParameter astTpRaw : nodeWithTypeParameters.getTypeParameters()) {
+                TypeParameter astTp = astTpRaw;
+                if (astTp.getName().getId().equals(name)) {
+                    return SymbolReference.solved(new JavaParserTypeParameter(astTp, typeSolver));
+                }
+            }
+        }
+
+        // Look into extended classes and implemented interfaces
+        for (ReferenceType ancestor : this.typeDeclaration.getAncestors()) {
+        	try {
+	            for (TypeDeclaration internalTypeDeclaration : ancestor.getTypeDeclaration().internalTypes()) {
+	                if (internalTypeDeclaration.getName().equals(name)) {
+	                    return SymbolReference.solved(internalTypeDeclaration);
+	                }
+	            }
+        	} catch (UnsupportedOperationException e) {
+	            // just continue using the next ancestor
+            }
+        }
+
+        return context.getParent().solveType(name, typeSolver);
+    }
+
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        List<MethodDeclaration> candidateMethods = typeDeclaration.getDeclaredMethods().stream()
+                .filter(m -> m.getName().equals(name))
+                .filter(m -> !staticOnly || (staticOnly &&  m.isStatic()))
+                .collect(Collectors.toList());
+        // We want to avoid infinite recursion in case of Object having Object as ancestor
+        if (!Object.class.getCanonicalName().equals(typeDeclaration.getQualifiedName())) {
+            for (ReferenceType ancestor : typeDeclaration.getAncestors()) {
+		// Avoid recursion on self
+                if (typeDeclaration != ancestor.getTypeDeclaration()) {
+                    SymbolReference<MethodDeclaration> res = MethodResolutionLogic
+                            .solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver);
+                    // consider methods from superclasses and only default methods from interfaces :
+                    // not true, we should keep abstract as a valid candidate
+                    // abstract are removed in MethodResolutionLogic.isApplicable is necessary
+                    if (res.isSolved()) {
+                        candidateMethods.add(res.getCorrespondingDeclaration());
+                    }
+		}
+            }
+        }
+        // We want to avoid infinite recursion when a class is using its own method
+        // see issue #75
+        if (candidateMethods.isEmpty()) {
+            SymbolReference<MethodDeclaration> parentSolution = context.getParent().solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+            if (parentSolution.isSolved()) {
+                candidateMethods.add(parentSolution.getCorrespondingDeclaration());
+            }
+        }
+
+        // if is interface and candidate method list is empty, we should check the Object Methods
+        if (candidateMethods.isEmpty() && typeDeclaration.isInterface()) {
+            SymbolReference<MethodDeclaration> res = MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver);
+            if (res.isSolved()) {
+                candidateMethods.add(res.getCorrespondingDeclaration());
+            }
+        }
+
+        return MethodResolutionLogic.findMostApplicable(candidateMethods, name, argumentsTypes, typeSolver);
+    }
+
+    public SymbolReference<ConstructorDeclaration> solveConstructor(List<Type> argumentsTypes, TypeSolver typeSolver) {
+        if (typeDeclaration instanceof ClassDeclaration) {
+            return ConstructorResolutionLogic.findMostApplicable(((ClassDeclaration) typeDeclaration).getConstructors(), argumentsTypes, typeSolver);
+        }
+        return SymbolReference.unsolved(ConstructorDeclaration.class);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java
new file mode 100644
index 0000000..02c69ee
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/LambdaExprContext.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.LambdaExpr;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic;
+import com.github.javaparser.symbolsolver.logic.InferenceContext;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.LambdaConstraintType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.MyObjectProvider;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+import javaslang.Tuple2;
+
+import java.util.*;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class LambdaExprContext extends AbstractJavaParserContext<LambdaExpr> {
+
+    public LambdaExprContext(LambdaExpr wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        for (Parameter parameter : wrappedNode.getParameters()) {
+            SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
+            int index = 0;
+            for (ValueDeclaration decl : sb.getSymbolDeclarations()) {
+                if (decl.getName().equals(name)) {
+                    if (getParentNode(wrappedNode) instanceof MethodCallExpr) {
+                        MethodCallExpr methodCallExpr = (MethodCallExpr) getParentNode(wrappedNode);
+                        MethodUsage methodUsage = JavaParserFacade.get(typeSolver).solveMethodAsUsage(methodCallExpr);
+                        int i = pos(methodCallExpr, wrappedNode);
+                        Type lambdaType = methodUsage.getParamTypes().get(i);
+
+                        // Get the functional method in order for us to resolve it's type arguments properly
+                        Optional<MethodUsage> functionalMethodOpt = FunctionalInterfaceLogic.getFunctionalMethod(lambdaType);
+                        if (functionalMethodOpt.isPresent()){
+                            MethodUsage functionalMethod = functionalMethodOpt.get();
+                            InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE);
+
+                            // Resolve each type variable of the lambda, and use this later to infer the type of each
+                            // implicit parameter
+                            inferenceContext.addPair(lambdaType, new ReferenceTypeImpl(lambdaType.asReferenceType().getTypeDeclaration(), typeSolver));
+
+                            // Find the position of this lambda argument
+                            boolean found = false;
+                            int lambdaParamIndex;
+                            for (lambdaParamIndex = 0; lambdaParamIndex < wrappedNode.getParameters().size(); lambdaParamIndex++){
+                                if (wrappedNode.getParameter(lambdaParamIndex).getName().getIdentifier().equals(name)){
+                                    found = true;
+                                    break;
+                                }
+                            }
+                            if (!found) { return Optional.empty(); }
+
+                            // Now resolve the argument type using the inference context
+                            Type argType = inferenceContext.resolve(inferenceContext.addSingle(functionalMethod.getParamType(lambdaParamIndex)));
+
+                            LambdaConstraintType conType;
+                            if (argType.isWildcard()){
+                                conType = LambdaConstraintType.bound(argType.asWildcard().getBoundedType());
+                            } else {
+                                conType = LambdaConstraintType.bound(argType);
+                            }
+                            Value value = new Value(conType, name);
+                            return Optional.of(value);
+                        } else{
+                            return Optional.empty();
+                        }
+                    } else if (getParentNode(wrappedNode) instanceof VariableDeclarator) {
+                        VariableDeclarator variableDeclarator = (VariableDeclarator) getParentNode(wrappedNode);
+                        Type t = JavaParserFacade.get(typeSolver).convertToUsageVariableType(variableDeclarator);
+                        Optional<MethodUsage> functionalMethod = FunctionalInterfaceLogic.getFunctionalMethod(t);
+                        if (functionalMethod.isPresent()) {
+                            Type lambdaType = functionalMethod.get().getParamType(index);
+
+                            // Replace parameter from declarator
+                            Map<TypeParameterDeclaration, Type> inferredTypes = new HashMap<>();
+                            if (lambdaType.isReferenceType()) {
+                                for (Tuple2<TypeParameterDeclaration, Type> entry : lambdaType.asReferenceType().getTypeParametersMap()) {
+                                    if (entry._2.isTypeVariable() && entry._2.asTypeParameter().declaredOnType()) {
+                                        Type ot = t.asReferenceType().typeParametersMap().getValue(entry._1);
+                                        lambdaType = lambdaType.replaceTypeVariables(entry._1, ot, inferredTypes);
+                                    }
+                                }
+                            } else if (lambdaType.isTypeVariable() && lambdaType.asTypeParameter().declaredOnType()) {
+                                lambdaType = t.asReferenceType().typeParametersMap().getValue(lambdaType.asTypeParameter());
+                            }
+
+                            Value value = new Value(lambdaType, name);
+                            return Optional.of(value);
+                        } else {
+                            throw new UnsupportedOperationException();
+                        }
+                    } else {
+                        throw new UnsupportedOperationException();
+                    }
+                }
+                index++;
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        return getParent().solveSymbolAsValue(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (Parameter parameter : wrappedNode.getParameters()) {
+            SymbolDeclarator sb = JavaParserFactory.getSymbolDeclarator(parameter, typeSolver);
+            SymbolReference<ValueDeclaration> symbolReference = solveWith(sb, name);
+            if (symbolReference.isSolved()) {
+                return symbolReference;
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        return getParent().solveType(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(
+            String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+
+    ///
+    /// Protected methods
+    ///
+
+    protected final Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) {
+        for (ValueDeclaration decl : symbolDeclarator.getSymbolDeclarations()) {
+            if (decl.getName().equals(name)) {
+
+                throw new UnsupportedOperationException();
+            }
+        }
+        return Optional.empty();
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private int pos(MethodCallExpr callExpr, Expression param) {
+        int i = 0;
+        for (Expression p : callExpr.getArguments()) {
+            if (p == param) {
+                return i;
+            }
+            i++;
+        }
+        throw new IllegalArgumentException();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java
new file mode 100644
index 0000000..094f29b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+import com.github.javaparser.symbolsolver.model.typesystem.ArrayType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import javaslang.Tuple2;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class MethodCallExprContext extends AbstractJavaParserContext<MethodCallExpr> {
+
+    ///
+    /// Constructors
+    ///
+
+    public MethodCallExprContext(MethodCallExpr wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    @Override
+    public Optional<Type> solveGenericType(String name, TypeSolver typeSolver) {
+        if(wrappedNode.getScope().isPresent()){
+            Type typeOfScope = JavaParserFacade.get(typeSolver).getType(wrappedNode.getScope().get());
+            Optional<Type> res = typeOfScope.asReferenceType().getGenericParameterByName(name);
+            return res;
+        } else{
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "MethodCallExprContext{wrapped=" + wrappedNode + "}";
+    }
+
+    @Override
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        if (wrappedNode.getScope().isPresent()) {
+            Expression scope = wrappedNode.getScope().get();
+            // Consider static method calls
+            if (scope instanceof NameExpr) {
+                String className = ((NameExpr) scope).getName().getId();
+                SymbolReference<TypeDeclaration> ref = solveType(className, typeSolver);
+                if (ref.isSolved()) {
+                    SymbolReference<MethodDeclaration> m = MethodResolutionLogic.solveMethodInType(ref.getCorrespondingDeclaration(), name, argumentsTypes, typeSolver);
+                    if (m.isSolved()) {
+                        MethodUsage methodUsage = new MethodUsage(m.getCorrespondingDeclaration());
+                        methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage);
+                        methodUsage = resolveMethodTypeParameters(methodUsage, argumentsTypes);
+                        return Optional.of(methodUsage);
+                    } else {
+                        throw new UnsolvedSymbolException(ref.getCorrespondingDeclaration().toString(),
+                                "Method '" + name + "' with parameterTypes " + argumentsTypes);
+                    }
+                }
+            }
+
+            Type typeOfScope = JavaParserFacade.get(typeSolver).getType(scope);
+            // we can replace the parameter types from the scope into the typeParametersValues
+
+            Map<TypeParameterDeclaration, Type> inferredTypes = new HashMap<>();
+            for (int i = 0; i < argumentsTypes.size(); i++) {
+                // by replacing types I can also find new equivalences
+                // for example if I replace T=U with String because I know that T=String I can derive that also U equal String
+                Type originalArgumentType = argumentsTypes.get(i);
+                Type updatedArgumentType = usingParameterTypesFromScope(typeOfScope, originalArgumentType, inferredTypes);
+                argumentsTypes.set(i, updatedArgumentType);
+            }
+            for (int i = 0; i < argumentsTypes.size(); i++) {
+                Type updatedArgumentType = applyInferredTypes(argumentsTypes.get(i), inferredTypes);
+                argumentsTypes.set(i, updatedArgumentType);
+            }
+
+            return solveMethodAsUsage(typeOfScope, name, argumentsTypes, typeSolver, this);
+        } else {
+            Context parentContext = getParent();
+            while (parentContext instanceof MethodCallExprContext) {
+                parentContext = parentContext.getParent();
+            }
+            return parentContext.solveMethodAsUsage(name, argumentsTypes, typeSolver);
+        }
+    }
+
+    private MethodUsage resolveMethodTypeParametersFromExplicitList(TypeSolver typeSolver, MethodUsage methodUsage) {
+        if (wrappedNode.getTypeArguments().isPresent()) {
+            final List<Type> typeArguments = new ArrayList<>();
+            for (com.github.javaparser.ast.type.Type ty : wrappedNode.getTypeArguments().get()) {
+                typeArguments.add(JavaParserFacade.get(typeSolver).convertToUsage(ty));
+            }
+
+            List<TypeParameterDeclaration> tyParamDecls = methodUsage.getDeclaration().getTypeParameters();
+            if (tyParamDecls.size() == typeArguments.size()) {
+                for (int i = 0; i < tyParamDecls.size(); i++) {
+                    methodUsage = methodUsage.replaceTypeParameter(tyParamDecls.get(i), typeArguments.get(i));
+                }
+            }
+        }
+
+        return methodUsage;
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        Context parentContext = getParent();
+        return parentContext.solveSymbolAsValue(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        if (wrappedNode.getScope().isPresent()) {
+            Expression scope = wrappedNode.getScope().get();
+
+            // consider static methods
+            if (scope instanceof NameExpr) {
+                NameExpr scopeAsName = (NameExpr) scope;
+                SymbolReference<TypeDeclaration> symbolReference = this.solveType(scopeAsName.getName().getId(), typeSolver);
+                if (symbolReference.isSolved() && symbolReference.getCorrespondingDeclaration().isType()) {
+                    TypeDeclaration typeDeclaration = symbolReference.getCorrespondingDeclaration().asType();
+                    return MethodResolutionLogic.solveMethodInType(typeDeclaration, name, argumentsTypes, false, typeSolver);
+                }
+            }
+
+            Type typeOfScope = null;
+            try {
+                typeOfScope = JavaParserFacade.get(typeSolver).getType(scope);
+            } catch (Exception e) {
+                throw new RuntimeException(String.format("Issue calculating the type of the scope of " + this), e);
+            }
+            if (typeOfScope.isWildcard()) {
+                if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) {
+                    return MethodResolutionLogic.solveMethodInType(typeOfScope.asWildcard().getBoundedType().asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver);
+                } else {
+                    return MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver);
+                }
+            } else if (typeOfScope.isArray()) {
+                // method call on array are Object methods
+                return MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver);
+            } else if (typeOfScope.isTypeVariable()) {
+                for (TypeParameterDeclaration.Bound bound : typeOfScope.asTypeParameter().getBounds(typeSolver)) {
+                    SymbolReference<MethodDeclaration> res = MethodResolutionLogic.solveMethodInType(bound.getType().asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver);
+                    if (res.isSolved()) {
+                        return res;
+                    }
+                }
+                return SymbolReference.unsolved(MethodDeclaration.class);
+            } else if (typeOfScope.isConstraint()){
+                return MethodResolutionLogic.solveMethodInType(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration(), name, argumentsTypes, typeSolver);
+            } else {
+                return MethodResolutionLogic.solveMethodInType(typeOfScope.asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver);
+            }
+        } else {
+            Type typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode);
+            return MethodResolutionLogic.solveMethodInType(typeOfScope.asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver);
+        }
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private Optional<MethodUsage> solveMethodAsUsage(ReferenceType refType, String name,
+                                                     List<Type> argumentsTypes, TypeSolver typeSolver,
+                                                     Context invokationContext) {
+        Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(refType.getTypeDeclaration(), name, argumentsTypes, typeSolver, invokationContext, refType.typeParametersValues());
+        if (ref.isPresent()) {
+            MethodUsage methodUsage = ref.get();
+
+            methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage);
+
+            // At this stage I should derive from the context and the value some information on the type parameters
+            // for example, when calling:
+            // myStream.collect(Collectors.toList())
+            // I should be able to figure out that considering the type of the stream (e.g., Stream<String>)
+            // and considering that Stream has this method:
+            //
+            // <R,A> R collect(Collector<? super T,A,R> collector)
+            //
+            // and collector has this method:
+            //
+            // static <T> Collector<T,?,List<T>>   toList()
+            //
+            // In this case collect.R has to be equal to List<toList.T>
+            // And toList.T has to be equal to ? super Stream.T
+            // Therefore R has to be equal to List<? super Stream.T>.
+            // In our example Stream.T equal to String, so the R (and the result of the call to collect) is
+            // List<? super String>
+
+            Map<TypeParameterDeclaration, Type> derivedValues = new HashMap<>();
+            for (int i = 0; i < methodUsage.getParamTypes().size(); i++) {
+                ParameterDeclaration parameter = methodUsage.getDeclaration().getParam(i);
+                Type parameterType = parameter.getType();
+                if (parameter.isVariadic()) {
+                	parameterType = parameterType.asArrayType().getComponentType();
+                }
+                inferTypes(argumentsTypes.get(i), parameterType, derivedValues);
+            }
+
+            for (Map.Entry<TypeParameterDeclaration, Type> entry : derivedValues.entrySet()){
+                methodUsage = methodUsage.replaceTypeParameter(entry.getKey(), entry.getValue());
+            }
+
+            Type returnType = refType.useThisTypeParametersOnTheGivenType(methodUsage.returnType());
+            if (returnType != methodUsage.returnType()) {
+                methodUsage = methodUsage.replaceReturnType(returnType);
+            }
+            for (int i = 0; i < methodUsage.getParamTypes().size(); i++) {
+                Type replaced = refType.useThisTypeParametersOnTheGivenType(methodUsage.getParamTypes().get(i));
+                methodUsage = methodUsage.replaceParamType(i, replaced);
+            }
+            return Optional.of(methodUsage);
+        } else {
+            return ref;
+        }
+    }
+
+    private void inferTypes(Type source, Type target, Map<TypeParameterDeclaration, Type> mappings) {
+        if (source.equals(target)) {
+            return;
+        }
+        if (source.isReferenceType() && target.isReferenceType()) {
+        	ReferenceType sourceRefType = source.asReferenceType();
+        	ReferenceType targetRefType = target.asReferenceType();
+            if (sourceRefType.getQualifiedName().equals(targetRefType.getQualifiedName())) {
+            	if (!sourceRefType.isRawType() && !targetRefType.isRawType()) {
+	                for (int i = 0; i < sourceRefType.typeParametersValues().size(); i++) {
+	                    inferTypes(sourceRefType.typeParametersValues().get(i), targetRefType.typeParametersValues().get(i), mappings);
+	                }
+            	}
+            }
+            return;
+        }
+        if (source.isReferenceType() && target.isWildcard()) {
+            if (target.asWildcard().isBounded()) {
+                inferTypes(source, target.asWildcard().getBoundedType(), mappings);
+                return;
+            }
+            return;
+        }
+        if (source.isWildcard() && target.isWildcard()) {
+            if (source.asWildcard().isBounded() && target.asWildcard().isBounded()){
+                inferTypes(source.asWildcard().getBoundedType(), target.asWildcard().getBoundedType(), mappings);
+            }
+            return;
+        }
+        if (source.isReferenceType() && target.isTypeVariable()) {
+            mappings.put(target.asTypeParameter(), source);
+            return;
+        }
+        if (source.isWildcard() && target.isTypeVariable()) {
+            mappings.put(target.asTypeParameter(), source);
+            return;
+        }
+        if (source.isArray() && target.isWildcard()){
+            if(target.asWildcard().isBounded()){
+                inferTypes(source, target.asWildcard().getBoundedType(), mappings);
+                return;
+            }
+            return;
+        }
+        if (source.isArray() && target.isTypeVariable()) {
+            mappings.put(target.asTypeParameter(), source);
+            return;
+        }
+
+        if (source.isWildcard() && target.isReferenceType()){
+            if (source.asWildcard().isBounded()){
+                inferTypes(source.asWildcard().getBoundedType(), target, mappings);
+            }
+            return;
+        }
+        if (source.isConstraint() && target.isReferenceType()){
+            inferTypes(source.asConstraintType().getBound(), target, mappings);
+            return;
+        }
+
+        if (source.isConstraint() && target.isTypeVariable()){
+            inferTypes(source.asConstraintType().getBound(), target, mappings);
+            return;
+        }
+        if (source.isTypeVariable() && target.isTypeVariable()) {
+            mappings.put(target.asTypeParameter(), source);
+            return;
+        }
+        if (source.isPrimitive() || target.isPrimitive()) {
+            return;
+        }
+        if (source.isNull()) {
+            return;
+        }
+        throw new RuntimeException(source.describe() + " " + target.describe());
+    }
+
+    private MethodUsage resolveMethodTypeParameters(MethodUsage methodUsage, List<Type> actualParamTypes) {
+        Map<TypeParameterDeclaration, Type> matchedTypeParameters = new HashMap<>();
+
+        if (methodUsage.getDeclaration().hasVariadicParameter()) {
+            if (actualParamTypes.size() == methodUsage.getDeclaration().getNumberOfParams()) {
+                // the varargs parameter is an Array, so extract the inner type
+                Type expectedType =
+                    methodUsage.getDeclaration().getLastParam().getType().asArrayType().getComponentType();
+                // the varargs corresponding type can be either T or Array<T>
+                Type actualType =
+                    actualParamTypes.get(actualParamTypes.size() - 1).isArray() ?
+                        actualParamTypes.get(actualParamTypes.size() - 1).asArrayType().getComponentType() :
+                        actualParamTypes.get(actualParamTypes.size() - 1);
+                if (!expectedType.isAssignableBy(actualType)) {
+                    for (TypeParameterDeclaration tp : methodUsage.getDeclaration().getTypeParameters()) {
+                        expectedType = MethodResolutionLogic.replaceTypeParam(expectedType, tp, typeSolver);
+                    }
+                }
+                if (!expectedType.isAssignableBy(actualType)) {
+                    // ok, then it needs to be wrapped
+                    throw new UnsupportedOperationException(
+                        String.format("Unable to resolve the type typeParametersValues in a MethodUsage. Expected type: %s, Actual type: %s. Method Declaration: %s. MethodUsage: %s",
+                                      expectedType,
+                                      actualType,
+                                      methodUsage.getDeclaration(),
+                                      methodUsage));
+                }
+                // match only the varargs type
+                matchTypeParameters(expectedType, actualType, matchedTypeParameters);
+            } else {
+                return methodUsage;
+            }
+        }
+
+        int until = methodUsage.getDeclaration().hasVariadicParameter() ?
+            actualParamTypes.size() - 1 :
+            actualParamTypes.size();
+
+        for (int i = 0; i < until; i++) {
+            Type expectedType = methodUsage.getParamType(i);
+            Type actualType = actualParamTypes.get(i);
+            matchTypeParameters(expectedType, actualType, matchedTypeParameters);
+        }
+        for (TypeParameterDeclaration tp : matchedTypeParameters.keySet()) {
+            methodUsage = methodUsage.replaceTypeParameter(tp, matchedTypeParameters.get(tp));
+        }
+        return methodUsage;
+    }
+
+    private void matchTypeParameters(Type expectedType, Type actualType, Map<TypeParameterDeclaration, Type> matchedTypeParameters) {
+        if (expectedType.isTypeVariable()) {
+            if (!actualType.isTypeVariable() && !actualType.isReferenceType()) {
+                throw new UnsupportedOperationException(actualType.getClass().getCanonicalName());
+            }
+            matchedTypeParameters.put(expectedType.asTypeParameter(), actualType);
+        } else if (expectedType.isArray()) {
+            if (!actualType.isArray()) {
+                throw new UnsupportedOperationException(actualType.getClass().getCanonicalName());
+            }
+            matchTypeParameters(
+                    expectedType.asArrayType().getComponentType(),
+                    actualType.asArrayType().getComponentType(),
+                    matchedTypeParameters);
+        } else if (expectedType.isReferenceType()) {
+            // avoid cases such as: "classX extends classY<Integer>"
+            if (actualType.asReferenceType().typeParametersValues().size() > 0) {
+                int i = 0;
+                for (Type tp : expectedType.asReferenceType().typeParametersValues()) {
+                    matchTypeParameters(tp, actualType.asReferenceType().typeParametersValues().get(i), matchedTypeParameters);
+                    i++;
+                }
+            }
+
+        } else if (expectedType.isPrimitive()) {
+            // nothing to do
+        } else if (expectedType.isWildcard()) {
+            // nothing to do
+        } else {
+            throw new UnsupportedOperationException(expectedType.getClass().getCanonicalName());
+        }
+    }
+
+    private Optional<MethodUsage> solveMethodAsUsage(TypeVariable tp, String name, List<Type> argumentsTypes, TypeSolver typeSolver, Context invokationContext) {
+        for (TypeParameterDeclaration.Bound bound : tp.asTypeParameter().getBounds(typeSolver)) {
+            Optional<MethodUsage> methodUsage = solveMethodAsUsage(bound.getType(), name, argumentsTypes, typeSolver, invokationContext);
+            if (methodUsage.isPresent()) {
+                return methodUsage;
+            }
+        }
+        return Optional.empty();
+    }
+
+    private Optional<MethodUsage> solveMethodAsUsage(Type type, String name, List<Type> argumentsTypes, TypeSolver typeSolver, Context invokationContext) {
+        if (type instanceof ReferenceType) {
+            return solveMethodAsUsage((ReferenceType) type, name, argumentsTypes, typeSolver, invokationContext);
+        } else if (type instanceof TypeVariable) {
+            return solveMethodAsUsage((TypeVariable) type, name, argumentsTypes, typeSolver, invokationContext);
+        } else if (type instanceof Wildcard) {
+            Wildcard wildcardUsage = (Wildcard) type;
+            if (wildcardUsage.isSuper()) {
+                return solveMethodAsUsage(wildcardUsage.getBoundedType(), name, argumentsTypes, typeSolver, invokationContext);
+            } else if (wildcardUsage.isExtends()) {
+                throw new UnsupportedOperationException("extends wildcard");
+            } else {
+                throw new UnsupportedOperationException("unbounded wildcard");
+            }
+        } else if (type instanceof LambdaConstraintType){
+            LambdaConstraintType constraintType = (LambdaConstraintType) type;
+            return solveMethodAsUsage(constraintType.getBound(), name, argumentsTypes, typeSolver, invokationContext);
+        } else if (type instanceof ArrayType) {
+            // An array inherits methods from Object not from it's component type
+            return solveMethodAsUsage(new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver), name, argumentsTypes, typeSolver, invokationContext);
+        } else {
+            throw new UnsupportedOperationException("type usage: " + type.getClass().getCanonicalName());
+        }
+    }
+
+    private Type usingParameterTypesFromScope(Type scope, Type type, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        if (type.isReferenceType()) {
+            for (Tuple2<TypeParameterDeclaration, Type> entry : type.asReferenceType().getTypeParametersMap()) {
+                if (entry._1.declaredOnType() && scope.asReferenceType().getGenericParameterByName(entry._1.getName()).isPresent()) {
+                    type = type.replaceTypeVariables(entry._1, scope.asReferenceType().getGenericParameterByName(entry._1.getName()).get(), inferredTypes);
+                }
+            }
+            return type;
+        } else {
+            return type;
+        }
+    }
+
+    private Type applyInferredTypes(Type type, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        for (TypeParameterDeclaration tp : inferredTypes.keySet()) {
+            type = type.replaceTypeVariables(tp, inferredTypes.get(tp), inferredTypes);
+        }
+        return type;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java
new file mode 100644
index 0000000..f7a2e44
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodContext.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class MethodContext extends AbstractMethodLikeDeclarationContext<MethodDeclaration> {
+
+    ///
+    /// Constructors
+    ///
+
+    public MethodContext(MethodDeclaration wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java
new file mode 100644
index 0000000..5074b5e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/StatementContext.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.expr.LambdaExpr;
+import com.github.javaparser.ast.nodeTypes.NodeWithStatements;
+import com.github.javaparser.ast.stmt.IfStmt;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class StatementContext<N extends Statement> extends AbstractJavaParserContext<N> {
+
+    public StatementContext(N wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    public static SymbolReference<? extends ValueDeclaration> solveInBlock(String name, TypeSolver typeSolver, Statement stmt) {
+        if (!(getParentNode(stmt) instanceof NodeWithStatements)) {
+            throw new IllegalArgumentException();
+        }
+        NodeWithStatements<?> blockStmt = (NodeWithStatements<?>) getParentNode(stmt);
+        int position = -1;
+        for (int i = 0; i < blockStmt.getStatements().size(); i++) {
+            if (blockStmt.getStatements().get(i).equals(stmt)) {
+                position = i;
+            }
+        }
+        if (position == -1) {
+            throw new RuntimeException();
+        }
+        for (int i = position - 1; i >= 0; i--) {
+            SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(blockStmt.getStatements().get(i), typeSolver);
+            SymbolReference<? extends ValueDeclaration> symbolReference = solveWith(symbolDeclarator, name);
+            if (symbolReference.isSolved()) {
+                return symbolReference;
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        return JavaParserFactory.getContext(getParentNode(stmt), typeSolver).solveSymbol(name, typeSolver);
+    }
+
+    public static Optional<Value> solveInBlockAsValue(String name, TypeSolver typeSolver, Statement stmt) {
+        if (!(getParentNode(stmt) instanceof NodeWithStatements)) {
+            throw new IllegalArgumentException();
+        }
+        NodeWithStatements<?> blockStmt = (NodeWithStatements<?>) getParentNode(stmt);
+        int position = -1;
+        for (int i = 0; i < blockStmt.getStatements().size(); i++) {
+            if (blockStmt.getStatements().get(i).equals(stmt)) {
+                position = i;
+            }
+        }
+        if (position == -1) {
+            throw new RuntimeException();
+        }
+        for (int i = position - 1; i >= 0; i--) {
+            SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(blockStmt.getStatements().get(i), typeSolver);
+            SymbolReference<? extends ValueDeclaration> symbolReference = solveWith(symbolDeclarator, name);
+            if (symbolReference.isSolved()) {
+                return Optional.of(Value.from(symbolReference.getCorrespondingDeclaration()));
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        return JavaParserFactory.getContext(getParentNode(stmt), typeSolver).solveSymbolAsValue(name, typeSolver);
+    }
+
+    @Override
+    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+
+        // if we're in a multiple Variable declaration line (for ex: double a=0, b=a;)
+        SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver);
+        Optional<Value> symbolReference = solveWithAsValue(symbolDeclarator, name, typeSolver);
+        if (symbolReference.isPresent()) {
+            return symbolReference;
+        }
+
+        // we should look in all the statements preceding, treating them as SymbolDeclarators
+        if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) {
+            return getParent().solveSymbolAsValue(name, typeSolver);
+        }
+        if (getParentNode(wrappedNode) instanceof LambdaExpr) {
+            return getParent().solveSymbolAsValue(name, typeSolver);
+        }
+        if (getParentNode(wrappedNode) instanceof IfStmt) {
+            return getParent().solveSymbolAsValue(name, typeSolver);
+        }
+        if (!(getParentNode(wrappedNode) instanceof NodeWithStatements)) {
+            return getParent().solveSymbolAsValue(name, typeSolver);
+        }
+        NodeWithStatements<?> nodeWithStmt = (NodeWithStatements<?>) getParentNode(wrappedNode);
+        int position = -1;
+        for (int i = 0; i < nodeWithStmt.getStatements().size(); i++) {
+            if (nodeWithStmt.getStatements().get(i).equals(wrappedNode)) {
+                position = i;
+            }
+        }
+        if (position == -1) {
+            throw new RuntimeException();
+        }
+        for (int i = position - 1; i >= 0; i--) {
+            symbolDeclarator = JavaParserFactory.getSymbolDeclarator(nodeWithStmt.getStatements().get(i), typeSolver);
+            symbolReference = solveWithAsValue(symbolDeclarator, name, typeSolver);
+            if (symbolReference.isPresent()) {
+                return symbolReference;
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        Context parentContext = getParent();
+        return parentContext.solveSymbolAsValue(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+
+        // if we're in a multiple Variable declaration line (for ex: double a=0, b=a;)
+        SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(wrappedNode, typeSolver);
+        SymbolReference<? extends ValueDeclaration> symbolReference = solveWith(symbolDeclarator, name);
+        if (symbolReference.isSolved()) {
+            return symbolReference;
+        }
+
+        // we should look in all the statements preceding, treating them as SymbolDeclarators
+        if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.MethodDeclaration) {
+            return getParent().solveSymbol(name, typeSolver);
+        }
+        if (getParentNode(wrappedNode) instanceof com.github.javaparser.ast.body.ConstructorDeclaration) {
+            return getParent().solveSymbol(name, typeSolver);
+        }
+        if (getParentNode(wrappedNode) instanceof LambdaExpr) {
+            return getParent().solveSymbol(name, typeSolver);
+        }
+        if (!(getParentNode(wrappedNode) instanceof NodeWithStatements)) {
+            return getParent().solveSymbol(name, typeSolver);
+        }
+        NodeWithStatements<?> nodeWithStmt = (NodeWithStatements<?>) getParentNode(wrappedNode);
+        int position = -1;
+        for (int i = 0; i < nodeWithStmt.getStatements().size(); i++) {
+            if (nodeWithStmt.getStatements().get(i).equals(wrappedNode)) {
+                position = i;
+            }
+        }
+        if (position == -1) {
+            throw new RuntimeException();
+        }
+        for (int i = position - 1; i >= 0; i--) {
+            symbolDeclarator = JavaParserFactory.getSymbolDeclarator(nodeWithStmt.getStatements().get(i), typeSolver);
+            symbolReference = solveWith(symbolDeclarator, name);
+            if (symbolReference.isSolved()) {
+                return symbolReference;
+            }
+        }
+
+        // if nothing is found we should ask the parent context
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        return getParent().solveType(name, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java
new file mode 100644
index 0000000..7deca86
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/SwitchEntryContext.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.ast.stmt.SwitchEntryStmt;
+import com.github.javaparser.ast.stmt.SwitchStmt;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+import java.util.List;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class SwitchEntryContext extends AbstractJavaParserContext<SwitchEntryStmt> {
+
+    public SwitchEntryContext(SwitchEntryStmt wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        SwitchStmt switchStmt = (SwitchStmt) getParentNode(wrappedNode);
+        Type type = JavaParserFacade.get(typeSolver).getType(switchStmt.getSelector());
+        if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isEnum()) {
+            if (type instanceof ReferenceTypeImpl) {
+                ReferenceTypeImpl typeUsageOfTypeDeclaration = (ReferenceTypeImpl) type;
+                if (typeUsageOfTypeDeclaration.getTypeDeclaration().hasField(name)) {
+                    return SymbolReference.solved(typeUsageOfTypeDeclaration.getTypeDeclaration().getField(name));
+                }
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        }
+
+        // look for declaration in other switch statements
+        for (SwitchEntryStmt seStmt : switchStmt.getEntries()) {
+            if (!seStmt.equals(wrappedNode)) {
+                for (Statement stmt : seStmt.getStatements()) {
+                    SymbolDeclarator symbolDeclarator = JavaParserFactory.getSymbolDeclarator(stmt, typeSolver);
+                    SymbolReference<? extends ValueDeclaration> symbolReference = solveWith(symbolDeclarator, name);
+                    if (symbolReference.isSolved()) {
+                        return symbolReference;
+                    }
+                }
+            }
+        }
+
+        return getParent().solveSymbol(name, typeSolver);
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java
new file mode 100644
index 0000000..c5dbe81
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/contexts/TryWithResourceContext.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.contexts;
+
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.stmt.BlockStmt;
+import com.github.javaparser.ast.stmt.TryStmt;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+public class TryWithResourceContext extends AbstractJavaParserContext<TryStmt> {
+
+    public TryWithResourceContext(TryStmt wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
+        for (VariableDeclarationExpr expr : wrappedNode.getResources()) {
+            for (VariableDeclarator v : expr.getVariables()) {
+                if (v.getName().getIdentifier().equals(name)) {
+                    JavaParserSymbolDeclaration decl = JavaParserSymbolDeclaration.localVar(v, typeSolver);
+                    return Optional.of(Value.from(decl));
+                }
+            }
+        }
+
+        if (getParentNode(wrappedNode) instanceof BlockStmt) {
+            return StatementContext.solveInBlockAsValue(name, typeSolver, wrappedNode);
+        } else {
+            return getParent().solveSymbolAsValue(name, typeSolver);
+        }
+    }
+
+    @Override
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (VariableDeclarationExpr expr : wrappedNode.getResources()) {
+            for (VariableDeclarator v : expr.getVariables()) {
+                if (v.getName().getIdentifier().equals(name)) {
+                    return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(v, typeSolver));
+                }
+            }
+        }
+
+        if (getParentNode(wrappedNode) instanceof BlockStmt) {
+            return StatementContext.solveInBlock(name, typeSolver, wrappedNode);
+        } else {
+            return getParent().solveSymbol(name, typeSolver);
+        }
+    }
+
+    @Override
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly, TypeSolver typeSolver) {
+        return getParent().solveMethod(name, argumentsTypes, false, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java
new file mode 100644
index 0000000..06f5457
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/DefaultConstructorDeclaration.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.symbolsolver.model.declarations.*;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+class DefaultConstructorDeclaration implements ConstructorDeclaration {
+
+    private ClassDeclaration classDeclaration;
+
+    DefaultConstructorDeclaration(ClassDeclaration classDeclaration) {
+        this.classDeclaration = classDeclaration;
+    }
+
+    @Override
+    public ClassDeclaration declaringType() {
+        return classDeclaration;
+    }
+
+    @Override
+    public int getNumberOfParams() {
+        return 0;
+    }
+
+    @Override
+    public ParameterDeclaration getParam(int i) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName() {
+        return classDeclaration.getName();
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return AccessLevel.PUBLIC;
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return Collections.emptyList();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java
new file mode 100644
index 0000000..7aa8ed9
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/Helper.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.PackageDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.AccessLevel;
+
+import java.util.EnumSet;
+import java.util.Optional;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+class Helper {
+
+    public static AccessLevel toAccessLevel(EnumSet<Modifier> modifiers) {
+        if (modifiers.contains(Modifier.PRIVATE)) {
+            return AccessLevel.PRIVATE;
+        } else if (modifiers.contains(Modifier.PROTECTED)) {
+            return AccessLevel.PROTECTED;
+        } else if (modifiers.contains(Modifier.PUBLIC)) {
+            return AccessLevel.PUBLIC;
+        } else {
+            return AccessLevel.PACKAGE_PROTECTED;
+        }
+    }
+
+    static String containerName(Node container) {
+        String packageName = getPackageName(container);
+        String className = getClassName("", container);
+        return packageName +
+                ((!packageName.isEmpty() && !className.isEmpty()) ? "." : "") +
+                className;
+    }
+
+    static String getPackageName(Node container) {
+        if (container instanceof CompilationUnit) {
+            Optional<PackageDeclaration> p = ((CompilationUnit) container).getPackageDeclaration();
+            if (p.isPresent()) {
+                return p.get().getName().toString();
+            }
+        } else if (container != null) {
+            return getPackageName(getParentNode(container));
+        }
+        return "";
+    }
+
+    static String getClassName(String base, Node container) {
+        if (container instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) {
+            String b = getClassName(base, getParentNode(container));
+            String cn = ((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) container).getName().getId();
+            if (b.isEmpty()) {
+                return cn;
+            } else {
+                return b + "." + cn;
+            }
+        } else if (container instanceof com.github.javaparser.ast.body.EnumDeclaration) {
+            String b = getClassName(base, getParentNode(container));
+            String cn = ((com.github.javaparser.ast.body.EnumDeclaration) container).getName().getId();
+            if (b.isEmpty()) {
+                return cn;
+            } else {
+                return b + "." + cn;
+            }
+        } else if (container != null) {
+            return getClassName(base, getParentNode(container));
+        }
+        return base;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java
new file mode 100644
index 0000000..4c6745d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnnotationDeclaration.java
@@ -0,0 +1,92 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserAnnotationDeclaration extends AbstractTypeDeclaration implements AnnotationDeclaration {
+
+    private com.github.javaparser.ast.body.AnnotationDeclaration wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserAnnotationDeclaration(com.github.javaparser.ast.body.AnnotationDeclaration wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String qualifiedName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getPackageName() {
+        return Helper.getPackageName(wrappedNode);
+    }
+
+    @Override
+    public String getClassName() {
+        return Helper.getClassName("", wrappedNode);
+    }
+
+    @Override
+    public String getQualifiedName() {
+        String containerName = Helper.containerName(getParentNode(wrappedNode));
+        if (containerName.isEmpty()) {
+            return wrappedNode.getName().getId();
+        } else {
+            return containerName + "." + wrappedNode.getName();
+        }
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        throw new UnsupportedOperationException("containerType is not supported for " + this.getClass().getCanonicalName());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java
new file mode 100644
index 0000000..e29a42e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclaration.java
@@ -0,0 +1,203 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.AccessLevel;
+import com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.FieldDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * An anonymous class declaration representation.
+ */
+public class JavaParserAnonymousClassDeclaration extends AbstractClassDeclaration {
+
+  private final TypeSolver typeSolver;
+  private final ObjectCreationExpr wrappedNode;
+  private final TypeDeclaration superTypeDeclaration;
+  private final String name = "Anonymous-" + UUID.randomUUID();
+
+  public JavaParserAnonymousClassDeclaration(ObjectCreationExpr wrappedNode,
+                                             TypeSolver typeSolver) {
+    this.typeSolver = typeSolver;
+    this.wrappedNode = wrappedNode;
+    superTypeDeclaration =
+        JavaParserFactory.getContext(wrappedNode.getParentNode().get(), typeSolver)
+                         .solveType(wrappedNode.getType().getName().getId(), typeSolver)
+                         .getCorrespondingDeclaration();
+  }
+
+  public TypeDeclaration getSuperTypeDeclaration() {
+    return superTypeDeclaration;
+  }
+
+  public <T extends Node> List<T> findMembersOfKind(final Class<T> memberClass) {
+    return wrappedNode
+        .getAnonymousClassBody()
+        .get()
+        .stream()
+        .filter(node -> memberClass.isAssignableFrom(node.getClass()))
+        .map(node -> (T) node)
+        .collect(Collectors.toList());
+  }
+
+  @Override
+  protected ReferenceType object() {
+    return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
+  }
+
+  @Override
+  public ReferenceType getSuperClass() {
+    return new ReferenceTypeImpl(superTypeDeclaration.asReferenceType(), typeSolver);
+  }
+
+  @Override
+  public List<ReferenceType> getInterfaces() {
+    return
+        superTypeDeclaration
+            .asReferenceType().getAncestors()
+            .stream()
+            .filter(type -> type.getTypeDeclaration().isInterface())
+            .collect(Collectors.toList());
+  }
+
+  @Override
+  public List<ConstructorDeclaration> getConstructors() {
+    return
+        findMembersOfKind(com.github.javaparser.ast.body.ConstructorDeclaration.class)
+            .stream()
+            .map(ctor -> new JavaParserConstructorDeclaration(this, ctor, typeSolver))
+            .collect(Collectors.toList());
+  }
+
+  @Override
+  public AccessLevel accessLevel() {
+    return AccessLevel.PRIVATE;
+  }
+
+  @Override
+  public List<ReferenceType> getAncestors() {
+    return
+        ImmutableList.
+            <ReferenceType>builder()
+            .add(getSuperClass())
+            .addAll(superTypeDeclaration.asReferenceType().getAncestors())
+            .build();
+  }
+
+  @Override
+  public List<FieldDeclaration> getAllFields() {
+
+    List<JavaParserFieldDeclaration> myFields =
+        findMembersOfKind(com.github.javaparser.ast.body.FieldDeclaration.class)
+            .stream()
+            .flatMap(field ->
+                         field.getVariables().stream()
+                              .map(variable -> new JavaParserFieldDeclaration(variable,
+                                                                              typeSolver)))
+            .collect(Collectors.toList());
+
+    List<FieldDeclaration> superClassFields =
+        getSuperClass().getTypeDeclaration().getAllFields();
+
+    List<FieldDeclaration> interfaceFields =
+        getInterfaces().stream()
+                       .flatMap(inteface -> inteface.getTypeDeclaration().getAllFields().stream())
+                       .collect(Collectors.toList());
+
+    return
+        ImmutableList
+        .<FieldDeclaration>builder()
+        .addAll(myFields)
+        .addAll(superClassFields)
+        .addAll(interfaceFields)
+        .build();
+  }
+
+  @Override
+  public Set<MethodDeclaration> getDeclaredMethods() {
+    return
+        findMembersOfKind(com.github.javaparser.ast.body.MethodDeclaration.class)
+            .stream()
+            .map(method -> new JavaParserMethodDeclaration(method, typeSolver))
+            .collect(Collectors.toSet());
+  }
+
+  @Override
+  public boolean isAssignableBy(Type type) {
+    return false;
+  }
+
+  @Override
+  public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+    return false;
+  }
+
+  @Override
+  public boolean hasDirectlyAnnotation(String qualifiedName) {
+    return false;
+  }
+
+  @Override
+  public String getPackageName() {
+    return Helper.getPackageName(wrappedNode);
+  }
+
+  @Override
+  public String getClassName() {
+    return Helper.getClassName("", wrappedNode);
+  }
+
+  @Override
+  public String getQualifiedName() {
+    String containerName = Helper.containerName(getParentNode(wrappedNode));
+    if (containerName.isEmpty()) {
+      return getName();
+    } else {
+      return containerName + "." + getName();
+    }
+  }
+
+  @Override
+  public Set<ReferenceTypeDeclaration> internalTypes() {
+    return
+        findMembersOfKind(com.github.javaparser.ast.body.TypeDeclaration.class)
+            .stream()
+            .map(typeMember -> JavaParserFacade.get(typeSolver).getTypeDeclaration(typeMember))
+            .collect(Collectors.toSet());
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public List<TypeParameterDeclaration> getTypeParameters() {
+    return Lists.newArrayList();
+  }
+
+  @Override
+  public Optional<ReferenceTypeDeclaration> containerType() {
+    throw new UnsupportedOperationException("containerType is not supported for " + this.getClass().getCanonicalName());
+  }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java
new file mode 100644
index 0000000..b7acdfd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserClassDeclaration.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.*;
+import com.github.javaparser.ast.expr.AnnotationExpr;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.FieldDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.LazyType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+import com.google.common.collect.ImmutableList;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserClassDeclaration extends AbstractClassDeclaration {
+
+    ///
+    /// Fields
+    ///
+
+    private TypeSolver typeSolver;
+    private com.github.javaparser.ast.body.ClassOrInterfaceDeclaration wrappedNode;
+    private JavaParserTypeAdapter<ClassOrInterfaceDeclaration> javaParserTypeAdapter;
+
+    ///
+    /// Constructors
+    ///
+
+    public JavaParserClassDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration wrappedNode,
+                                      TypeSolver typeSolver) {
+        if (wrappedNode.isInterface()) {
+            throw new IllegalArgumentException("Interface given");
+        }
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+        this.javaParserTypeAdapter = new JavaParserTypeAdapter<ClassOrInterfaceDeclaration>(wrappedNode, typeSolver);
+    }
+
+    ///
+    /// Public methods: from Object
+    ///
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        JavaParserClassDeclaration that = (JavaParserClassDeclaration) o;
+
+        if (!wrappedNode.equals(that.wrappedNode)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return wrappedNode.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "JavaParserClassDeclaration{" +
+                "wrappedNode=" + wrappedNode +
+                '}';
+    }
+
+    ///
+    /// Public methods: fields
+    ///
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        ArrayList<FieldDeclaration> fields = new ArrayList<>();
+        for (BodyDeclaration<?> member : wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.FieldDeclaration) {
+                com.github.javaparser.ast.body.FieldDeclaration field = (com.github.javaparser.ast.body.FieldDeclaration) member;
+                for (VariableDeclarator vd : field.getVariables()) {
+                    fields.add(new JavaParserFieldDeclaration(vd, typeSolver));
+                }
+            }
+        }
+
+        ClassDeclaration superclass = (ClassDeclaration) this.getSuperClass().getTypeDeclaration();
+        if (superclass!=this)
+            fields.addAll(superclass.getAllFields());
+
+        getInterfaces().forEach(interf -> interf.getTypeDeclaration().getAllFields().forEach(f -> {
+            fields.add(f);
+        }));
+
+        return fields;
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes) {
+        Context ctx = getContext();
+        return ctx.solveMethod(name, parameterTypes, false, typeSolver);
+    }
+
+    @Deprecated
+    public Context getContext() {
+        return JavaParserFactory.getContext(wrappedNode, typeSolver);
+    }
+
+    public Type getUsage(Node node) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public ReferenceType getSuperClass() {
+        if (wrappedNode.getExtendedTypes().isEmpty()) {
+            return object();
+        } else {
+            return toReferenceType(wrappedNode.getExtendedTypes().get(0));
+        }
+    }
+
+    @Override
+    public List<ReferenceType> getInterfaces() {
+        List<ReferenceType> interfaces = new ArrayList<>();
+        if (wrappedNode.getImplementedTypes() != null) {
+            for (ClassOrInterfaceType t : wrappedNode.getImplementedTypes()) {
+                interfaces.add(toReferenceType(t));
+            }
+        }
+        return interfaces;
+    }
+
+    @Override
+    public List<ConstructorDeclaration> getConstructors() {
+        List<ConstructorDeclaration> declared = new LinkedList<>();
+        for (BodyDeclaration<?> member : wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.ConstructorDeclaration) {
+                com.github.javaparser.ast.body.ConstructorDeclaration constructorDeclaration = (com.github.javaparser.ast.body.ConstructorDeclaration) member;
+                declared.add(new JavaParserConstructorDeclaration(this, constructorDeclaration, typeSolver));
+            }
+        }
+        if (declared.isEmpty()) {
+            // If there are no constructors insert the default constructor
+            return ImmutableList.of(new DefaultConstructorDeclaration(this));
+        } else {
+            return declared;
+        }
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        for (AnnotationExpr annotationExpr : wrappedNode.getAnnotations()) {
+            if (solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return wrappedNode.isInterface();
+    }
+
+    @Override
+    public String getPackageName() {
+        return javaParserTypeAdapter.getPackageName();
+    }
+
+    @Override
+    public String getClassName() {
+        return javaParserTypeAdapter.getClassName();
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return javaParserTypeAdapter.getQualifiedName();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return javaParserTypeAdapter.isAssignableBy(other);
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        return javaParserTypeAdapter.isAssignableBy(type);
+    }
+
+    @Override
+    public boolean canBeAssignedTo(ReferenceTypeDeclaration other) {
+        // TODO consider generic types
+        if (this.getQualifiedName().equals(other.getQualifiedName())) {
+            return true;
+        }
+        ClassDeclaration superclass = (ClassDeclaration) getSuperClass().getTypeDeclaration();
+        if (superclass != null) {
+            // We want to avoid infinite recursion in case of Object having Object as ancestor
+            if (Object.class.getCanonicalName().equals(superclass.getQualifiedName())) {
+                return true;
+            }
+            if (superclass.canBeAssignedTo(other)) {
+                return true;
+            }
+        }
+
+        if (this.wrappedNode.getImplementedTypes() != null) {
+            for (ClassOrInterfaceType type : wrappedNode.getImplementedTypes()) {
+                ReferenceTypeDeclaration ancestor = (ReferenceTypeDeclaration) new SymbolSolver(typeSolver).solveType(type);
+                if (ancestor.canBeAssignedTo(other)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return false;
+    }
+
+    @Deprecated
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        if (this.wrappedNode.getName().getId().equals(name)) {
+            return SymbolReference.solved(this);
+        }
+        SymbolReference<TypeDeclaration> ref = javaParserTypeAdapter.solveType(name, typeSolver);
+        if (ref.isSolved()) {
+            return ref;
+        }
+
+        String prefix = wrappedNode.getName() + ".";
+        if (name.startsWith(prefix) && name.length() > prefix.length()) {
+            return new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
+        }
+
+        return getContext().getParent().solveType(name, typeSolver);
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        List<ReferenceType> ancestors = new ArrayList<>();
+        ReferenceType superclass = getSuperClass();
+        if (superclass != null) {
+            ancestors.add(superclass);
+        }
+        if (wrappedNode.getImplementedTypes() != null) {
+            for (ClassOrInterfaceType implemented : wrappedNode.getImplementedTypes()) {
+                ReferenceType ancestor = toReferenceType(implemented);
+                ancestors.add(ancestor);
+            }
+        }
+        return ancestors;
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        Set<MethodDeclaration> methods = new HashSet<>();
+        for (BodyDeclaration<?> member : wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) {
+                methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver));
+            }
+        }
+        return methods;
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return this.wrappedNode.getTypeParameters().stream().map(
+                (tp) -> new JavaParserTypeParameter(tp, typeSolver)
+        ).collect(Collectors.toList());
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserClassDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public com.github.javaparser.ast.body.ClassOrInterfaceDeclaration getWrappedNode() {
+        return wrappedNode;
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return Helper.toAccessLevel(wrappedNode.getModifiers());
+    }
+
+    ///
+    /// Protected methods
+    ///
+
+    @Override
+    protected ReferenceType object() {
+        return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
+    }
+
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        Set<ReferenceTypeDeclaration> res = new HashSet<>();
+        for (BodyDeclaration member : this.wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
+                res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member));
+            }
+        }
+        return res;
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return javaParserTypeAdapter.containerType();
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private ReferenceType toReferenceType(ClassOrInterfaceType classOrInterfaceType) {
+        String className = classOrInterfaceType.getName().getId();
+        if (classOrInterfaceType.getScope().isPresent()) {
+            // look for the qualified name (for example class of type Rectangle2D.Double)
+            className = classOrInterfaceType.getScope().get().toString() + "." + className;
+        }
+        SymbolReference<TypeDeclaration> ref = solveType(className, typeSolver);
+        if (!ref.isSolved()) {
+            Optional<ClassOrInterfaceType> localScope = classOrInterfaceType.getScope();
+            if (localScope.isPresent()) {
+                String localName = localScope.get().getName().getId() + "." + classOrInterfaceType.getName().getId();
+                ref = solveType(localName, typeSolver);
+            }
+        }
+        if (!ref.isSolved()) {
+            throw new UnsolvedSymbolException(classOrInterfaceType.getName().getId());
+        }
+        if (!classOrInterfaceType.getTypeArguments().isPresent()) {
+            return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), typeSolver);
+        }
+        List<Type> superClassTypeParameters = classOrInterfaceType.getTypeArguments().get()
+                .stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta)))
+                .collect(Collectors.toList());
+        return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), superClassTypeParameters, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java
new file mode 100644
index 0000000..1c34e4c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserConstructorDeclaration.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserConstructorDeclaration implements ConstructorDeclaration {
+
+    private ClassDeclaration classDeclaration;
+    private com.github.javaparser.ast.body.ConstructorDeclaration wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserConstructorDeclaration(ClassDeclaration classDeclaration, com.github.javaparser.ast.body.ConstructorDeclaration wrappedNode,
+                                            TypeSolver typeSolver) {
+        this.classDeclaration = classDeclaration;
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public ClassDeclaration declaringType() {
+        return classDeclaration;
+    }
+
+    @Override
+    public int getNumberOfParams() {
+        return this.wrappedNode.getParameters().size();
+    }
+
+    @Override
+    public ParameterDeclaration getParam(int i) {
+        if (i < 0 || i >= getNumberOfParams()) {
+            throw new IllegalArgumentException(String.format("No param with index %d. Number of params: %d", i, getNumberOfParams()));
+        }
+        return new JavaParserParameterDeclaration(wrappedNode.getParameters().get(i), typeSolver);
+    }
+
+    @Override
+    public String getName() {
+        return this.classDeclaration.getName();
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserConstructorDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public com.github.javaparser.ast.body.ConstructorDeclaration getWrappedNode() {
+        return wrappedNode;
+    }
+    
+    @Override
+    public AccessLevel accessLevel() {
+        return Helper.toAccessLevel(wrappedNode.getModifiers());
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration.java
new file mode 100644
index 0000000..de76be1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumConstantDeclaration.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserEnumConstantDeclaration implements ValueDeclaration {
+
+    private TypeSolver typeSolver;
+    private com.github.javaparser.ast.body.EnumConstantDeclaration wrappedNode;
+
+    public JavaParserEnumConstantDeclaration(com.github.javaparser.ast.body.EnumConstantDeclaration wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public Type getType() {
+        return new ReferenceTypeImpl(new JavaParserEnumDeclaration((EnumDeclaration) getParentNode(wrappedNode), typeSolver), typeSolver);
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserEnumConstantDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public com.github.javaparser.ast.body.EnumConstantDeclaration getWrappedNode() {
+        return wrappedNode;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java
new file mode 100644
index 0000000..fb858f9
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserEnumDeclaration.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ArrayType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParametersMap;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserEnumDeclaration extends AbstractTypeDeclaration implements EnumDeclaration {
+
+    private TypeSolver typeSolver;
+    private com.github.javaparser.ast.body.EnumDeclaration wrappedNode;
+    private JavaParserTypeAdapter javaParserTypeAdapter;
+
+    public JavaParserEnumDeclaration(com.github.javaparser.ast.body.EnumDeclaration wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+        this.javaParserTypeAdapter = new JavaParserTypeAdapter(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public String toString() {
+        return "JavaParserEnumDeclaration{" +
+                "wrappedNode=" + wrappedNode +
+                '}';
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        Set<MethodDeclaration> methods = new HashSet<>();
+        for (BodyDeclaration member : wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) {
+                methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver));
+            }
+        }
+        return methods;
+    }
+
+    public Context getContext() {
+        return JavaParserFactory.getContext(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean isType() {
+        return true;
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean canBeAssignedTo(ReferenceTypeDeclaration other) {
+        // Enums cannot be extended
+        if (other.getQualifiedName().equals(this.getQualifiedName())) {
+            return true;
+        }
+        if (other.getQualifiedName().equals(Enum.class.getCanonicalName())) {
+            return true;
+        }
+        // Enum implements Comparable and Serializable
+        if (other.getQualifiedName().equals(Comparable.class.getCanonicalName())) {
+            return true;
+        }
+        if (other.getQualifiedName().equals(Serializable.class.getCanonicalName())) {
+            return true;
+        }
+        if (other.getQualifiedName().equals(Object.class.getCanonicalName())) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isClass() {
+        return false;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return false;
+    }
+
+    @Override
+    public String getPackageName() {
+        return javaParserTypeAdapter.getPackageName();
+    }
+
+    @Override
+    public String getClassName() {
+        return javaParserTypeAdapter.getClassName();
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return javaParserTypeAdapter.getQualifiedName();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return javaParserTypeAdapter.isAssignableBy(other);
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        return javaParserTypeAdapter.isAssignableBy(type);
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        JavaParserEnumDeclaration that = (JavaParserEnumDeclaration) o;
+
+        if (!wrappedNode.equals(that.wrappedNode)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return wrappedNode.hashCode();
+    }
+
+    @Deprecated
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> parameterTypes, TypeSolver typeSolver, Context invokationContext, List<Type> typeParameterValues) {
+        if (name.equals("values") && parameterTypes.isEmpty()) {
+            return Optional.of(new ValuesMethod(this, typeSolver).getUsage(null));
+        }
+        // TODO add methods inherited from Enum
+        return getContext().solveMethodAsUsage(name, parameterTypes, typeSolver);
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        ArrayList<FieldDeclaration> fields = new ArrayList<>();
+        if (this.wrappedNode.getMembers() != null) {
+            for (BodyDeclaration member : this.wrappedNode.getMembers()) {
+                if (member instanceof com.github.javaparser.ast.body.FieldDeclaration) {
+                    com.github.javaparser.ast.body.FieldDeclaration field = (com.github.javaparser.ast.body.FieldDeclaration) member;
+                    for (VariableDeclarator vd : field.getVariables()) {
+                        fields.add(new JavaParserFieldDeclaration(vd, typeSolver));
+                    }
+                }
+            }
+        }
+
+        if (this.wrappedNode.getEntries() != null) {
+            for (EnumConstantDeclaration member : this.wrappedNode.getEntries()) {
+                fields.add(new JavaParserFieldDeclaration(member, typeSolver));
+            }
+        }
+
+        return fields;
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        List<ReferenceType> ancestors = new ArrayList<>();
+        ReferenceType enumClass = ReflectionFactory.typeUsageFor(Enum.class, typeSolver).asReferenceType();
+        TypeParameterDeclaration eTypeParameter = enumClass.getTypeDeclaration().getTypeParameters().get(0);
+        enumClass = enumClass.deriveTypeParameters(new TypeParametersMap.Builder().setValue(eTypeParameter, new ReferenceTypeImpl(this, typeSolver)).build());
+        ancestors.add(enumClass);
+        if (wrappedNode.getImplementedTypes() != null) {
+            for (ClassOrInterfaceType implementedType : wrappedNode.getImplementedTypes()) {
+                SymbolReference<TypeDeclaration> implementedDeclRef = new SymbolSolver(typeSolver).solveTypeInType(this, implementedType.getName().getId());
+                if (!implementedDeclRef.isSolved()) {
+                    throw new UnsolvedSymbolException(implementedType.getName().getId());
+                }
+                ancestors.add(new ReferenceTypeImpl((ReferenceTypeDeclaration) implementedDeclRef.getCorrespondingDeclaration(), typeSolver));
+            }
+        }
+        return ancestors;
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserEnumDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public com.github.javaparser.ast.body.EnumDeclaration getWrappedNode() {
+        return wrappedNode;
+    }
+
+    // Needed by ContextHelper
+    public static class ValuesMethod implements MethodDeclaration {
+
+        private JavaParserEnumDeclaration enumDeclaration;
+        private TypeSolver typeSolver;
+
+        public ValuesMethod(JavaParserEnumDeclaration enumDeclaration, TypeSolver typeSolver) {
+            this.enumDeclaration = enumDeclaration;
+            this.typeSolver = typeSolver;
+        }
+
+        @Override
+        public ReferenceTypeDeclaration declaringType() {
+            return enumDeclaration;
+        }
+
+        @Override
+        public Type getReturnType() {
+            return new ArrayType(new ReferenceTypeImpl(enumDeclaration, typeSolver));
+        }
+
+        @Override
+        public int getNumberOfParams() {
+            return 0;
+        }
+
+        @Override
+        public ParameterDeclaration getParam(int i) {
+            throw new UnsupportedOperationException();
+        }
+
+        public MethodUsage getUsage(Node node) {
+            throw new UnsupportedOperationException();
+        }
+
+        public MethodUsage resolveTypeVariables(Context context, List<Type> parameterTypes) {
+            return new MethodUsage(this);
+        }
+
+        @Override
+        public boolean isAbstract() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isDefaultMethod() {
+            return false;
+        }
+
+        @Override
+        public boolean isStatic() {
+            return false;
+        }
+
+        @Override
+        public String getName() {
+            return "values";
+        }
+
+        @Override
+        public List<TypeParameterDeclaration> getTypeParameters() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public AccessLevel accessLevel() {
+            return Helper.toAccessLevel(enumDeclaration.getWrappedNode().getModifiers());
+        }
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        Set<ReferenceTypeDeclaration> res = new HashSet<>();
+        for (BodyDeclaration member : this.wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
+                res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member));
+            }
+        }
+        return res;
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return javaParserTypeAdapter.containerType();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java
new file mode 100644
index 0000000..49bb68a
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserFieldDeclaration.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.body.EnumConstantDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.declarations.AccessLevel;
+import com.github.javaparser.symbolsolver.model.declarations.FieldDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.Optional;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserFieldDeclaration implements FieldDeclaration {
+
+    private VariableDeclarator variableDeclarator;
+    private com.github.javaparser.ast.body.FieldDeclaration wrappedNode;
+    private EnumConstantDeclaration enumConstantDeclaration;
+    private TypeSolver typeSolver;
+
+    public JavaParserFieldDeclaration(VariableDeclarator variableDeclarator, TypeSolver typeSolver) {
+        if (typeSolver == null) {
+            throw new IllegalArgumentException("typeSolver should not be null");
+        }
+        this.variableDeclarator = variableDeclarator;
+        this.typeSolver = typeSolver;
+        if (!(getParentNode(variableDeclarator) instanceof com.github.javaparser.ast.body.FieldDeclaration)) {
+            throw new IllegalStateException(getParentNode(variableDeclarator).getClass().getCanonicalName());
+        }
+        this.wrappedNode = (com.github.javaparser.ast.body.FieldDeclaration) getParentNode(variableDeclarator);
+    }
+
+    public JavaParserFieldDeclaration(EnumConstantDeclaration enumConstantDeclaration, TypeSolver typeSolver) {
+        if (typeSolver == null) {
+            throw new IllegalArgumentException("typeSolver should not be null");
+        }
+        this.enumConstantDeclaration = enumConstantDeclaration;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public Type getType() {
+        if (enumConstantDeclaration != null) {
+            com.github.javaparser.ast.body.EnumDeclaration enumDeclaration = (com.github.javaparser.ast.body.EnumDeclaration) getParentNode(enumConstantDeclaration);
+            return new ReferenceTypeImpl(new JavaParserEnumDeclaration(enumDeclaration, typeSolver), typeSolver);
+        } else {
+            Type retType = JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), wrappedNode);
+            return retType;
+        }
+    }
+
+    @Override
+    public String getName() {
+        if (enumConstantDeclaration != null) {
+            return enumConstantDeclaration.getName().getId();
+        } else {
+            return variableDeclarator.getName().getId();
+        }
+    }
+
+    @Override
+    public boolean isStatic() {
+        return wrappedNode.getModifiers().contains(Modifier.STATIC);
+    }
+
+    @Override
+    public boolean isField() {
+        return true;
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserFieldDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public com.github.javaparser.ast.body.FieldDeclaration getWrappedNode() {
+        return wrappedNode;
+    }
+
+    @Override
+    public String toString() {
+        return "JPField{" + getName() + "}";
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return Helper.toAccessLevel(wrappedNode.getModifiers());
+    }
+
+    @Override
+    public TypeDeclaration declaringType() {
+        Optional<com.github.javaparser.ast.body.TypeDeclaration> typeDeclaration = Navigator.findAncestor(wrappedNode, com.github.javaparser.ast.body.TypeDeclaration.class);
+        if (typeDeclaration.isPresent()) {
+            return JavaParserFacade.get(typeSolver).getTypeDeclaration(typeDeclaration.get());
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java
new file mode 100644
index 0000000..7c50127
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserInterfaceDeclaration.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.AnnotationExpr;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.LazyType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserInterfaceDeclaration extends AbstractTypeDeclaration implements InterfaceDeclaration {
+
+    private TypeSolver typeSolver;
+    private ClassOrInterfaceDeclaration wrappedNode;
+    private JavaParserTypeAdapter javaParserTypeAdapter;
+
+    public JavaParserInterfaceDeclaration(ClassOrInterfaceDeclaration wrappedNode, TypeSolver typeSolver) {
+        if (!wrappedNode.isInterface()) {
+            throw new IllegalArgumentException();
+        }
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+        this.javaParserTypeAdapter = new JavaParserTypeAdapter(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        Set<MethodDeclaration> methods = new HashSet<>();
+        for (BodyDeclaration member : wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) {
+                methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver));
+            }
+        }
+        return methods;
+    }
+
+    public Context getContext() {
+        return JavaParserFactory.getContext(wrappedNode, typeSolver);
+    }
+
+    public Type getUsage(Node node) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        JavaParserInterfaceDeclaration that = (JavaParserInterfaceDeclaration) o;
+
+        if (!wrappedNode.equals(that.wrappedNode)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return wrappedNode.hashCode();
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public InterfaceDeclaration asInterface() {
+        return this;
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        for (AnnotationExpr annotationExpr : wrappedNode.getAnnotations()) {
+            if (solveType(annotationExpr.getName().getId(), typeSolver).getCorrespondingDeclaration().getQualifiedName().equals(canonicalName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return true;
+    }
+
+    @Override
+    public List<ReferenceType> getInterfacesExtended() {
+        List<ReferenceType> interfaces = new ArrayList<>();
+        if (wrappedNode.getImplementedTypes() != null) {
+            for (ClassOrInterfaceType t : wrappedNode.getImplementedTypes()) {
+                interfaces.add(new ReferenceTypeImpl(solveType(t.getName().getId(), typeSolver).getCorrespondingDeclaration().asInterface(), typeSolver));
+            }
+        }
+        return interfaces;
+    }
+
+    @Override
+    public String getPackageName() {
+        return javaParserTypeAdapter.getPackageName();
+    }
+
+    @Override
+    public String getClassName() {
+        return javaParserTypeAdapter.getClassName();
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return javaParserTypeAdapter.getQualifiedName();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return javaParserTypeAdapter.isAssignableBy(other);
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        return javaParserTypeAdapter.isAssignableBy(type);
+    }
+
+    @Override
+    public boolean canBeAssignedTo(ReferenceTypeDeclaration other) {
+        // TODO consider generic types
+        if (this.getQualifiedName().equals(other.getQualifiedName())) {
+            return true;
+        }
+        if (this.wrappedNode.getExtendedTypes() != null) {
+            for (ClassOrInterfaceType type : wrappedNode.getExtendedTypes()) {
+                ReferenceTypeDeclaration ancestor = (ReferenceTypeDeclaration) new SymbolSolver(typeSolver).solveType(type);
+                if (ancestor.canBeAssignedTo(other)) {
+                    return true;
+                }
+            }
+        }
+
+        if (this.wrappedNode.getImplementedTypes() != null) {
+            for (ClassOrInterfaceType type : wrappedNode.getImplementedTypes()) {
+                ReferenceTypeDeclaration ancestor = (ReferenceTypeDeclaration) new SymbolSolver(typeSolver).solveType(type);
+                if (ancestor.canBeAssignedTo(other)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return false;
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        ArrayList<FieldDeclaration> fields = new ArrayList<>();
+        for (BodyDeclaration member : wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.FieldDeclaration) {
+                com.github.javaparser.ast.body.FieldDeclaration field = (com.github.javaparser.ast.body.FieldDeclaration) member;
+                for (VariableDeclarator vd : field.getVariables()) {
+                    fields.add(new JavaParserFieldDeclaration(vd, typeSolver));
+                }
+            }
+        }
+
+        getAncestors().forEach(a -> {
+            if (a.getTypeDeclaration() != this) {
+                fields.addAll(a.getTypeDeclaration().getAllFields());
+            }
+        });
+
+        return fields;
+    }
+
+
+    @Override
+    public String toString() {
+        return "JavaParserInterfaceDeclaration{" +
+                "wrappedNode=" + wrappedNode +
+                '}';
+    }
+
+    @Deprecated
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        if (this.wrappedNode.getName().getId().equals(name)) {
+            return SymbolReference.solved(this);
+        }
+        SymbolReference<TypeDeclaration> ref = javaParserTypeAdapter.solveType(name, typeSolver);
+        if (ref.isSolved()) {
+            return ref;
+        }
+
+        String prefix = wrappedNode.getName() + ".";
+        if (name.startsWith(prefix) && name.length() > prefix.length()) {
+            return new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
+        }
+
+        return getContext().getParent().solveType(name, typeSolver);
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        List<ReferenceType> ancestors = new ArrayList<>();
+        if (wrappedNode.getExtendedTypes() != null) {
+            for (ClassOrInterfaceType extended : wrappedNode.getExtendedTypes()) {
+                ancestors.add(toReferenceType(extended));
+            }
+        }
+        if (wrappedNode.getImplementedTypes() != null) {
+            for (ClassOrInterfaceType implemented : wrappedNode.getImplementedTypes()) {
+                ancestors.add(toReferenceType(implemented));
+            }
+        }
+        return ancestors;
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        if (this.wrappedNode.getTypeParameters() == null) {
+            return Collections.emptyList();
+        } else {
+            return this.wrappedNode.getTypeParameters().stream().map(
+                    (tp) -> new JavaParserTypeParameter(tp, typeSolver)
+            ).collect(Collectors.toList());
+        }
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserInterfaceDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public ClassOrInterfaceDeclaration getWrappedNode() {
+        return wrappedNode;
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return Helper.toAccessLevel(wrappedNode.getModifiers());
+    }
+
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        Set<ReferenceTypeDeclaration> res = new HashSet<>();
+        for (BodyDeclaration member : this.wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
+                res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member));
+            }
+        }
+        return res;
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return javaParserTypeAdapter.containerType();
+    }
+
+    ///
+    /// Private methods
+    ///
+
+    private ReferenceType toReferenceType(ClassOrInterfaceType classOrInterfaceType) {
+        SymbolReference<? extends TypeDeclaration> ref = null;
+        if (classOrInterfaceType.toString().indexOf('.') > -1) {
+            ref = typeSolver.tryToSolveType(classOrInterfaceType.toString());
+        }
+        if (ref == null || !ref.isSolved()) {
+            ref = solveType(classOrInterfaceType.toString(), typeSolver);
+        }
+        if (!ref.isSolved()) {
+            ref = solveType(classOrInterfaceType.getName().getId(), typeSolver);
+        }
+        if (!ref.isSolved()) {
+            throw new UnsolvedSymbolException(classOrInterfaceType.getName().getId());
+        }
+        if (!classOrInterfaceType.getTypeArguments().isPresent()) {
+            return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), typeSolver);
+        }
+        List<Type> superClassTypeParameters = classOrInterfaceType.getTypeArguments().get()
+                .stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta)))
+                .collect(Collectors.toList());
+        return new ReferenceTypeImpl(ref.getCorrespondingDeclaration().asReferenceType(), superClassTypeParameters, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java
new file mode 100644
index 0000000..b22c3a9
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserMethodDeclaration.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.expr.ObjectCreationExpr;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserMethodDeclaration implements MethodDeclaration {
+
+    private com.github.javaparser.ast.body.MethodDeclaration wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserMethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public String toString() {
+        return "JavaParserMethodDeclaration{" +
+                "wrappedNode=" + wrappedNode +
+                ", typeSolver=" + typeSolver +
+                '}';
+    }
+
+    @Override
+    public ReferenceTypeDeclaration declaringType() {
+        if (getParentNode(wrappedNode) instanceof ObjectCreationExpr) {
+            ObjectCreationExpr parentNode = (ObjectCreationExpr) getParentNode(wrappedNode);
+            return new JavaParserAnonymousClassDeclaration(parentNode, typeSolver);
+        } else {
+            return JavaParserFactory.toTypeDeclaration(getParentNode(wrappedNode), typeSolver);
+        }
+    }
+
+    @Override
+    public Type getReturnType() {
+        return JavaParserFacade.get(typeSolver).convert(wrappedNode.getType(), getContext());
+    }
+
+    @Override
+    public int getNumberOfParams() {
+        return wrappedNode.getParameters().size();
+    }
+
+    @Override
+    public ParameterDeclaration getParam(int i) {
+        if (i < 0 || i >= getNumberOfParams()) {
+            throw new IllegalArgumentException(String.format("No param with index %d. Number of params: %d", i, getNumberOfParams()));
+        }
+        return new JavaParserParameterDeclaration(wrappedNode.getParameters().get(i), typeSolver);
+    }
+
+    public MethodUsage getUsage(Node node) {
+        throw new UnsupportedOperationException();
+    }
+
+    public MethodUsage resolveTypeVariables(Context context, List<Type> parameterTypes) {
+        return new MethodDeclarationCommonLogic(this, typeSolver).resolveTypeVariables(context, parameterTypes);
+    }
+
+    private Context getContext() {
+        return JavaParserFactory.getContext(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return !wrappedNode.getBody().isPresent();
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public boolean isField() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isParameter() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return this.wrappedNode.getTypeParameters().stream().map((astTp) -> new JavaParserTypeParameter(astTp, typeSolver)).collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean isDefaultMethod() {
+        return wrappedNode.isDefault();
+    }
+
+    @Override
+    public boolean isStatic() {
+        return wrappedNode.isStatic();
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserMethodDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public com.github.javaparser.ast.body.MethodDeclaration getWrappedNode() {
+        return wrappedNode;
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return Helper.toAccessLevel(wrappedNode.getModifiers());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java
new file mode 100644
index 0000000..c0dee1f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserParameterDeclaration.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.declarations.ParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ArrayType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserParameterDeclaration implements ParameterDeclaration {
+
+    private Parameter wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserParameterDeclaration(Parameter wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return true;
+    }
+
+    @Override
+    public boolean isVariadic() {
+        return wrappedNode.isVarArgs();
+    }
+
+    @Override
+    public boolean isType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Type getType() {
+        Type res = JavaParserFacade.get(typeSolver).convert(wrappedNode.getType(), wrappedNode);
+        if (isVariadic()) {
+            res = new ArrayType(res);
+        }
+        return res;
+    }
+
+    @Override
+    public ParameterDeclaration asParameter() {
+        return this;
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserParameterDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public Parameter getWrappedNode() {
+        return wrappedNode;
+    }
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java
new file mode 100644
index 0000000..5a05506
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserSymbolDeclaration.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.LambdaExpr;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ArrayType;
+import com.github.javaparser.symbolsolver.model.typesystem.PrimitiveType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserSymbolDeclaration implements ValueDeclaration {
+
+    private String name;
+    private Node wrappedNode;
+    private boolean field;
+    private boolean parameter;
+    private boolean variable;
+    private TypeSolver typeSolver;
+
+    private JavaParserSymbolDeclaration(Node wrappedNode, String name, TypeSolver typeSolver, boolean field, boolean parameter, boolean variable) {
+        this.name = name;
+        this.wrappedNode = wrappedNode;
+        this.field = field;
+        this.variable = variable;
+        this.parameter = parameter;
+        this.typeSolver = typeSolver;
+    }
+
+    public static JavaParserFieldDeclaration field(VariableDeclarator wrappedNode, TypeSolver typeSolver) {
+        return new JavaParserFieldDeclaration(wrappedNode, typeSolver);
+    }
+
+    public static JavaParserParameterDeclaration parameter(Parameter parameter, TypeSolver typeSolver) {
+        return new JavaParserParameterDeclaration(parameter, typeSolver);
+    }
+
+    public static JavaParserSymbolDeclaration localVar(VariableDeclarator variableDeclarator, TypeSolver typeSolver) {
+        return new JavaParserSymbolDeclaration(variableDeclarator, variableDeclarator.getName().getId(), typeSolver, false, false, true);
+    }
+
+    public static int getParamPos(Parameter parameter) {
+        int pos = 0;
+        for (Node node : getParentNode(parameter).getChildNodes()) {
+            if (node == parameter) {
+                return pos;
+            } else if (node instanceof Parameter) {
+                pos++;
+            }
+        }
+        return pos;
+    }
+
+    public static int getParamPos(Node node) {
+        if (getParentNode(node) instanceof MethodCallExpr) {
+            MethodCallExpr call = (MethodCallExpr) getParentNode(node);
+            for (int i = 0; i < call.getArguments().size(); i++) {
+                if (call.getArguments().get(i) == node) return i;
+            }
+            throw new IllegalStateException();
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "JavaParserSymbolDeclaration{" +
+                "name='" + name + '\'' +
+                ", wrappedNode=" + wrappedNode +
+                '}';
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean isField() {
+        return field;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return parameter;
+    }
+
+    @Override
+    public boolean isType() {
+        return false;
+    }
+
+    @Override
+    public Type getType() {
+        if (wrappedNode instanceof Parameter) {
+            Parameter parameter = (Parameter) wrappedNode;
+            if (getParentNode(wrappedNode) instanceof LambdaExpr) {
+                int pos = getParamPos(parameter);
+                Type lambdaType = JavaParserFacade.get(typeSolver).getType(getParentNode(wrappedNode));
+
+                // TODO understand from the context to which method this corresponds
+                //MethodDeclaration methodDeclaration = JavaParserFacade.get(typeSolver).getMethodCalled
+                //MethodDeclaration methodCalled = JavaParserFacade.get(typeSolver).solve()
+                throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName());
+            } else {
+                Type rawType = null;
+                if (parameter.getType() instanceof com.github.javaparser.ast.type.PrimitiveType) {
+                    rawType = PrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) parameter.getType()).getType().name());
+                } else {
+                    rawType = JavaParserFacade.get(typeSolver).convertToUsage(parameter.getType(), wrappedNode);
+                }
+                if (parameter.isVarArgs()) {
+                    return new ArrayType(rawType);
+                } else {
+                    return rawType;
+                }
+            }
+        } else if (wrappedNode instanceof VariableDeclarator) {
+            VariableDeclarator variableDeclarator = (VariableDeclarator) wrappedNode;
+            if (getParentNode(wrappedNode) instanceof VariableDeclarationExpr) {
+                Type type = JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver));
+                return type;
+            } else if (getParentNode(wrappedNode) instanceof FieldDeclaration) {
+                return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver));
+            } else {
+                throw new UnsupportedOperationException(getParentNode(wrappedNode).getClass().getCanonicalName());
+            }
+        } else {
+            throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName());
+        }
+    }
+
+    @Override
+    public TypeDeclaration asType() {
+        throw new UnsupportedOperationException(this.getClass().getCanonicalName() + ": wrapping " + this.getWrappedNode().getClass().getCanonicalName());
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserSymbolDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public Node getWrappedNode() {
+        return wrappedNode;
+    }
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java
new file mode 100644
index 0000000..97d1ab6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeAdapter.java
@@ -0,0 +1,120 @@
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.BodyDeclaration;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.nodeTypes.NodeWithMembers;
+import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
+import com.github.javaparser.ast.nodeTypes.NodeWithTypeParameters;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserTypeAdapter<T extends Node & NodeWithSimpleName<T> & NodeWithMembers<T> & NodeWithTypeParameters<T>> {
+
+    private T wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserTypeAdapter(T wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    public String getPackageName() {
+        return Helper.getPackageName(wrappedNode);
+    }
+
+    public String getClassName() {
+        return Helper.getClassName("", wrappedNode);
+    }
+
+    public String getQualifiedName() {
+        String containerName = Helper.containerName(getParentNode(wrappedNode));
+        if (containerName.isEmpty()) {
+            return wrappedNode.getName().getId();
+        } else {
+            return containerName + "." + wrappedNode.getName().getId();
+        }
+    }
+
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        List<ReferenceType> ancestorsOfOther = other.getAllAncestors();
+        ancestorsOfOther.add(new ReferenceTypeImpl(other, typeSolver));
+        for (ReferenceType ancestorOfOther : ancestorsOfOther) {
+            if (ancestorOfOther.getQualifiedName().equals(this.getQualifiedName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isAssignableBy(Type type) {
+        if (type.isNull()) {
+            return true;
+        }
+        if (type.isReferenceType()) {
+            ReferenceTypeDeclaration other = typeSolver.solveType(type.describe());
+            return isAssignableBy(other);
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver) {
+        if (this.wrappedNode.getTypeParameters() != null) {
+            for (com.github.javaparser.ast.type.TypeParameter typeParameter : this.wrappedNode.getTypeParameters()) {
+                if (typeParameter.getName().getId().equals(name)) {
+                    return SymbolReference.solved(new JavaParserTypeVariableDeclaration(typeParameter, typeSolver));
+                }
+            }
+        }
+
+        // Internal classes
+        for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) {
+            if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
+                com.github.javaparser.ast.body.TypeDeclaration<?> internalType = (com.github.javaparser.ast.body.TypeDeclaration<?>) member;
+                String prefix = internalType.getName() + ".";
+                if (internalType.getName().getId().equals(name)) {
+                    if (internalType instanceof ClassOrInterfaceDeclaration) {
+                        return SymbolReference.solved(new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver));
+                    } else if (internalType instanceof EnumDeclaration) {
+                        return SymbolReference.solved(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver));
+                    } else {
+                        throw new UnsupportedOperationException();
+                    }
+                } else if (name.startsWith(prefix) && name.length() > prefix.length()) {
+                    if (internalType instanceof ClassOrInterfaceDeclaration) {
+                        return new JavaParserClassDeclaration((com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) internalType, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
+                    } else if (internalType instanceof EnumDeclaration) {
+                        return new SymbolSolver(typeSolver).solveTypeInType(new JavaParserEnumDeclaration((com.github.javaparser.ast.body.EnumDeclaration) internalType, typeSolver), name.substring(prefix.length()));
+                    } else {
+                        throw new UnsupportedOperationException();
+                    }
+                }
+            }
+        }
+        return SymbolReference.unsolved(TypeDeclaration.class);
+    }
+
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        Optional<Node> parent = wrappedNode.getParentNode();
+        return parent.isPresent() ? 
+                Optional.of(JavaParserFactory.toTypeDeclaration(parent.get(), typeSolver)) :
+                Optional.empty();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java
new file mode 100644
index 0000000..0755969
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeParameter.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserTypeParameter extends AbstractTypeDeclaration implements TypeParameterDeclaration {
+
+    private com.github.javaparser.ast.type.TypeParameter wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserTypeParameter(com.github.javaparser.ast.type.TypeParameter wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return Collections.emptySet();
+    }
+
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes) {
+        return getContext().solveMethod(name, parameterTypes, false, typeSolver);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof JavaParserTypeParameter)) return false;
+
+        JavaParserTypeParameter that = (JavaParserTypeParameter) o;
+
+        if (wrappedNode != null ? !wrappedNode.equals(that.wrappedNode) : that.wrappedNode != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = wrappedNode != null ? wrappedNode.hashCode() : 0;
+        result = 31 * result + (typeSolver != null ? typeSolver.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return isAssignableBy(new ReferenceTypeImpl(other, typeSolver));
+    }
+
+    @Override
+    public String getContainerQualifiedName() {
+        TypeParametrizable container = getContainer();
+        if (container instanceof ReferenceTypeDeclaration) {
+            return ((ReferenceTypeDeclaration) container).getQualifiedName();
+        } else if (container instanceof JavaParserConstructorDeclaration) {
+            return ((JavaParserConstructorDeclaration) container).getQualifiedSignature();
+        } else {
+            return ((JavaParserMethodDeclaration) container).getQualifiedSignature();
+        }
+    }
+
+    @Override
+    public String getContainerId() {
+        TypeParametrizable container = getContainer();
+        if (container instanceof ReferenceTypeDeclaration) {
+            return ((ReferenceTypeDeclaration) container).getId();
+        } else if (container instanceof JavaParserConstructorDeclaration) {
+            return ((JavaParserConstructorDeclaration) container).getQualifiedSignature();
+        } else {
+            return ((JavaParserMethodDeclaration) container).getQualifiedSignature();
+        }
+    }
+
+    @Override
+    public TypeParametrizable getContainer() {
+        Node parentNode = getParentNode(wrappedNode);
+        if (parentNode instanceof com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) {
+            com.github.javaparser.ast.body.ClassOrInterfaceDeclaration jpTypeDeclaration = (com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) parentNode;
+            return JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration);
+        } else if (parentNode instanceof com.github.javaparser.ast.body.ConstructorDeclaration){
+            com.github.javaparser.ast.body.ConstructorDeclaration jpConstructorDeclaration = (com.github.javaparser.ast.body.ConstructorDeclaration) parentNode;
+            Optional<ClassOrInterfaceDeclaration> jpTypeDeclaration = jpConstructorDeclaration.getAncestorOfType(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class);
+            if (jpTypeDeclaration.isPresent()) {
+                ReferenceTypeDeclaration typeDeclaration = JavaParserFacade.get(typeSolver).getTypeDeclaration(jpTypeDeclaration.get());
+                if (typeDeclaration.isClass()) {
+                    return new JavaParserConstructorDeclaration(typeDeclaration.asClass(), jpConstructorDeclaration, typeSolver);
+                }
+            }
+        } else {
+            com.github.javaparser.ast.body.MethodDeclaration jpMethodDeclaration = (com.github.javaparser.ast.body.MethodDeclaration) parentNode;
+            return new JavaParserMethodDeclaration(jpMethodDeclaration, typeSolver);
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return String.format("%s.%s", getContainerQualifiedName(), getName());
+    }
+
+    @Override
+    public List<Bound> getBounds(TypeSolver typeSolver) {
+        return wrappedNode.getTypeBound().stream().map((astB) -> toBound(astB, typeSolver)).collect(Collectors.toList());
+    }
+
+    private Bound toBound(ClassOrInterfaceType classOrInterfaceType, TypeSolver typeSolver) {
+        Type type = JavaParserFacade.get(typeSolver).convertToUsage(classOrInterfaceType, classOrInterfaceType);
+        Bound bound = Bound.extendsBound(type);
+        return bound;
+    }
+
+    public Context getContext() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Type getUsage(Node node) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public FieldDeclaration getField(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasField(String name) {
+        return false;
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return true;
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserTypeParameter.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public com.github.javaparser.ast.type.TypeParameter getWrappedNode() {
+        return wrappedNode;
+    }
+
+    @Override
+    public String toString() {
+        return "JPTypeParameter(" + wrappedNode.getName() + ", bounds=" + wrappedNode.getTypeBound() + ")";
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        TypeParametrizable container = getContainer();
+        if (container instanceof ReferenceTypeDeclaration) {
+            return Optional.of((ReferenceTypeDeclaration) container);
+        }
+        return Optional.empty();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java
new file mode 100644
index 0000000..576552e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserTypeVariableDeclaration.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.type.TypeParameter;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.FieldDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserTypeVariableDeclaration extends AbstractTypeDeclaration {
+
+    private TypeParameter wrappedNode;
+    private TypeSolver typeSolver;
+
+    public JavaParserTypeVariableDeclaration(TypeParameter wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return isAssignableBy(new ReferenceTypeImpl(other, typeSolver));
+    }
+
+    @Override
+    public String getPackageName() {
+        return Helper.getPackageName(wrappedNode);
+    }
+
+    @Override
+    public String getClassName() {
+        return Helper.getClassName("", wrappedNode);
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return getName();
+    }
+
+    public Context getContext() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        return "JavaParserTypeVariableDeclaration{" +
+                wrappedNode.getName() +
+                '}';
+    }
+
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Type getUsage(Node node) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        if (type.isTypeVariable()) {
+            throw new UnsupportedOperationException("Is this type variable declaration assignable by " + type.describe());
+        } else {
+            throw new UnsupportedOperationException("Is this type variable declaration assignable by " + type);
+        }
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return true;
+    }
+
+    @Override
+    public FieldDeclaration getField(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasField(String name) {
+        return false;
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public String getName() {
+        return wrappedNode.getName().getId();
+    }
+
+    @Override
+    public boolean isField() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isParameter() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isType() {
+        return true;
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isClass() {
+        return false;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return false;
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    public TypeParameterDeclaration asTypeParameter() {
+        return new JavaParserTypeParameter(this.wrappedNode, typeSolver);
+    }
+
+    /**
+     * Returns the JavaParser node associated with this JavaParserTypeVariableDeclaration.
+     *
+     * @return A visitable JavaParser node wrapped by this object.
+     */
+    public TypeParameter getWrappedNode() {
+        return wrappedNode;
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return asTypeParameter().containerType();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator.java
new file mode 100644
index 0000000..14fdafc
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/AbstractSymbolDeclarator.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarators;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator;
+
+/**
+ * @author Federico Tomassetti
+ */
+public abstract class AbstractSymbolDeclarator<N extends Node> implements SymbolDeclarator {
+
+    protected N wrappedNode;
+    protected TypeSolver typeSolver;
+
+    public AbstractSymbolDeclarator(N wrappedNode, TypeSolver typeSolver) {
+        this.wrappedNode = wrappedNode;
+        this.typeSolver = typeSolver;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator.java
new file mode 100644
index 0000000..10c9278
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/FieldSymbolDeclarator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarators;
+
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class FieldSymbolDeclarator extends AbstractSymbolDeclarator<FieldDeclaration> {
+
+    public FieldSymbolDeclarator(FieldDeclaration wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public List<ValueDeclaration> getSymbolDeclarations() {
+        List<ValueDeclaration> symbols = new LinkedList<>();
+        for (VariableDeclarator v : wrappedNode.getVariables()) {
+            symbols.add(JavaParserSymbolDeclaration.field(v, typeSolver));
+        }
+        return symbols;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator.java
new file mode 100644
index 0000000..532af11
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/NoSymbolDeclarator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarators;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class NoSymbolDeclarator<N extends Node> extends AbstractSymbolDeclarator<N> {
+
+    public NoSymbolDeclarator(N wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public List<ValueDeclaration> getSymbolDeclarations() {
+        return Collections.emptyList();
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator.java
new file mode 100644
index 0000000..2717381
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/ParameterSymbolDeclarator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarators;
+
+import com.github.javaparser.ast.body.Parameter;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ParameterSymbolDeclarator extends AbstractSymbolDeclarator<Parameter> {
+
+    public ParameterSymbolDeclarator(Parameter wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+    }
+
+    @Override
+    public List<ValueDeclaration> getSymbolDeclarations() {
+        List<ValueDeclaration> symbols = new LinkedList<>();
+        symbols.add(JavaParserSymbolDeclaration.parameter(wrappedNode, typeSolver));
+        return symbols;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java
new file mode 100644
index 0000000..5ae5e38
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/declarators/VariableSymbolDeclarator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javaparsermodel.declarators;
+
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class VariableSymbolDeclarator extends AbstractSymbolDeclarator<VariableDeclarationExpr> {
+
+    public VariableSymbolDeclarator(VariableDeclarationExpr wrappedNode, TypeSolver typeSolver) {
+        super(wrappedNode, typeSolver);
+        if (getParentNode(wrappedNode) instanceof FieldDeclaration) {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public List<ValueDeclaration> getSymbolDeclarations() {
+        List<ValueDeclaration> symbols = wrappedNode.getVariables().stream().map(
+                v -> JavaParserSymbolDeclaration.localVar(v, typeSolver)
+        ).collect(
+                Collectors.toCollection(() -> new LinkedList<>()));
+        return symbols;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/package-info.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/package-info.java
new file mode 100644
index 0000000..9ddf1cf
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javaparsermodel/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementation of model based on JavaParser.
+ */
+package com.github.javaparser.symbolsolver.javaparsermodel;
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java
new file mode 100644
index 0000000..9fb72da
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
+import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+import javassist.bytecode.AccessFlag;
+import javassist.bytecode.BadBytecode;
+import javassist.bytecode.SignatureAttribute;
+import javassist.bytecode.SyntheticAttribute;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistClassDeclaration extends AbstractClassDeclaration {
+
+    private CtClass ctClass;
+    private TypeSolver typeSolver;
+    private JavassistTypeDeclarationAdapter javassistTypeDeclarationAdapter;
+
+    public JavassistClassDeclaration(CtClass ctClass, TypeSolver typeSolver) {
+        if (ctClass == null) {
+            throw new IllegalArgumentException();
+        }
+        if (ctClass.isInterface() || ctClass.isAnnotation() || ctClass.isPrimitive() || ctClass.isEnum()) {
+            throw new IllegalArgumentException("Trying to instantiate a JavassistClassDeclaration with something which is not a class: " + ctClass.toString());
+        }
+        this.ctClass = ctClass;
+        this.typeSolver = typeSolver;
+        this.javassistTypeDeclarationAdapter = new JavassistTypeDeclarationAdapter(ctClass, typeSolver);
+    }
+
+    @Override
+    protected ReferenceType object() {
+        return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return javassistTypeDeclarationAdapter.getDeclaredMethods();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return isAssignableBy(new ReferenceTypeImpl(other, typeSolver));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        JavassistClassDeclaration that = (JavassistClassDeclaration) o;
+
+        if (!ctClass.equals(that.ctClass)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return ctClass.hashCode();
+    }
+
+    @Override
+    public String getPackageName() {
+        return ctClass.getPackageName();
+    }
+
+    @Override
+    public String getClassName() {
+        String className = ctClass.getName().replace('$', '.');
+        if (getPackageName() != null) {
+            return className.substring(getPackageName().length() + 1, className.length());
+        }
+        return className;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return ctClass.getName().replace('$', '.');
+    }
+
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver,
+                                                    Context invokationContext, List<Type> typeParameterValues) {
+        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
+    }
+
+    @Deprecated
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (CtField field : ctClass.getDeclaredFields()) {
+            if (field.getName().equals(name)) {
+                return SymbolReference.solved(new JavassistFieldDeclaration(field, typeSolver));
+            }
+        }
+
+        try {
+            CtClass superClass = ctClass.getSuperclass();
+            if (superClass != null) {
+                SymbolReference<? extends ValueDeclaration> ref = new JavassistClassDeclaration(superClass, typeSolver).solveSymbol(name, typeSolver);
+                if (ref.isSolved()) {
+                    return ref;
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        try {
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                SymbolReference<? extends ValueDeclaration> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveSymbol(name, typeSolver);
+                if (ref.isSolved()) {
+                    return ref;
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        return SymbolReference.unsolved(ValueDeclaration.class);
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        List<ReferenceType> ancestors = new LinkedList<>();
+        if (getSuperClass() != null) {
+            ancestors.add(getSuperClass());
+        }
+        ancestors.addAll(getInterfaces());
+        return ancestors;
+    }
+
+    @Deprecated
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly) {
+        List<MethodDeclaration> candidates = new ArrayList<>();
+        Predicate<CtMethod> staticOnlyCheck = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
+        for (CtMethod method : ctClass.getDeclaredMethods()) {
+            boolean isSynthetic = method.getMethodInfo().getAttribute(SyntheticAttribute.tag) != null;
+            boolean isNotBridge =  (method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0;
+            if (method.getName().equals(name) && !isSynthetic && isNotBridge && staticOnlyCheck.test(method)) {
+                candidates.add(new JavassistMethodDeclaration(method, typeSolver));
+            }
+        }
+
+        try {
+            CtClass superClass = ctClass.getSuperclass();
+            if (superClass != null) {
+                SymbolReference<MethodDeclaration> ref = new JavassistClassDeclaration(superClass, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
+                if (ref.isSolved()) {
+                    candidates.add(ref.getCorrespondingDeclaration());
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        try {
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                SymbolReference<MethodDeclaration> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
+                if (ref.isSolved()) {
+                    candidates.add(ref.getCorrespondingDeclaration());
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        return MethodResolutionLogic.findMostApplicable(candidates, name, argumentsTypes, typeSolver);
+    }
+
+    public Type getUsage(Node node) {
+        return new ReferenceTypeImpl(this, typeSolver);
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        if (type.isNull()) {
+            return true;
+        }
+
+        if (type instanceof LambdaArgumentTypePlaceholder) {
+            return isFunctionalInterface();
+        }
+
+        // TODO look into generics
+        if (type.describe().equals(this.getQualifiedName())) {
+            return true;
+        }
+        try {
+            if (this.ctClass.getSuperclass() != null
+                    && new JavassistClassDeclaration(this.ctClass.getSuperclass(), typeSolver).isAssignableBy(type)) {
+                return true;
+            }
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                if (new JavassistInterfaceDeclaration(interfaze, typeSolver).isAssignableBy(type)) {
+                    return true;
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return false;
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+      return javassistTypeDeclarationAdapter.getDeclaredFields();
+    }
+
+    @Override
+    public String getName() {
+        String[] nameElements = ctClass.getSimpleName().replace('$', '.').split("\\.");
+        return nameElements[nameElements.length - 1];
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean isType() {
+        return true;
+    }
+
+    @Override
+    public boolean isClass() {
+        return !ctClass.isInterface();
+    }
+
+    @Override
+    public ReferenceType getSuperClass() {
+        try {
+            if (ctClass.getSuperclass() == null) {
+                return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
+            }
+            if (ctClass.getGenericSignature() == null) {
+                return new ReferenceTypeImpl(new JavassistClassDeclaration(ctClass.getSuperclass(), typeSolver), typeSolver);
+            }
+
+            SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature());
+            return JavassistUtils.signatureTypeToType(classSignature.getSuperClass(), typeSolver, this).asReferenceType();
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (BadBytecode e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<ReferenceType> getInterfaces() {
+        try {
+            if (ctClass.getGenericSignature() == null) {
+                return Arrays.stream(ctClass.getInterfaces())
+                        .map(i -> new JavassistInterfaceDeclaration(i, typeSolver))
+                        .map(i -> new ReferenceTypeImpl(i, typeSolver))
+                        .collect(Collectors.toList());
+            } else {
+                SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature());
+                return Arrays.stream(classSignature.getInterfaces())
+                        .map(i -> JavassistUtils.signatureTypeToType(i, typeSolver, this).asReferenceType())
+                        .collect(Collectors.toList());
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (BadBytecode e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public boolean isInterface() {
+        return ctClass.isInterface();
+    }
+
+    @Override
+    public String toString() {
+        return "JavassistClassDeclaration {" + ctClass.getName() + '}';
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return javassistTypeDeclarationAdapter.getTypeParameters();
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return JavassistFactory.modifiersToAccessLevel(ctClass.getModifiers());
+    }
+
+    @Override
+    public List<ConstructorDeclaration> getConstructors() {
+      return javassistTypeDeclarationAdapter.getConstructors();
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return javassistTypeDeclarationAdapter.containerType();
+    }
+
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        try {
+            /*
+            Get all internal types of the current class and get their corresponding ReferenceTypeDeclaration.
+            Finally, return them in a Set.
+             */
+            return Arrays.stream(ctClass.getDeclaredClasses()).map(itype -> JavassistFactory.toTypeDeclaration(itype, typeSolver)).collect(Collectors.toSet());
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ReferenceTypeDeclaration getInternalType(String name) {
+        /*
+        The name of the ReferenceTypeDeclaration could be composed of the internal class and the outer class, e.g. A$B. That's why we search the internal type in the ending part.
+        In case the name is composed of the internal type only, i.e. f.getName() returns B, it will also works.
+         */
+        Optional<ReferenceTypeDeclaration> type =
+                this.internalTypes().stream().filter(f -> f.getName().endsWith(name)).findFirst();
+        return type.orElseThrow(() ->
+                new UnsolvedSymbolException("Internal type not found: " + name));
+    }
+
+    @Override
+    public boolean hasInternalType(String name) {
+        /*
+        The name of the ReferenceTypeDeclaration could be composed of the internal class and the outer class, e.g. A$B. That's why we search the internal type in the ending part.
+        In case the name is composed of the internal type only, i.e. f.getName() returns B, it will also works.
+         */
+        return this.internalTypes().stream().anyMatch(f -> f.getName().endsWith(name));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration.java
new file mode 100644
index 0000000..8f1e195
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistConstructorDeclaration.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import javassist.CtConstructor;
+import javassist.NotFoundException;
+import javassist.bytecode.BadBytecode;
+import javassist.bytecode.SignatureAttribute;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Fred Lefévère-Laoide
+ */
+public class JavassistConstructorDeclaration implements ConstructorDeclaration {
+    private CtConstructor ctConstructor;
+    private TypeSolver typeSolver;
+
+    public JavassistConstructorDeclaration(CtConstructor ctConstructor, TypeSolver typeSolver) {
+        this.ctConstructor = ctConstructor;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public String toString() {
+        return "JavassistMethodDeclaration{" +
+                "CtConstructor=" + ctConstructor +
+                '}';
+    }
+
+    @Override
+    public String getName() {
+        return ctConstructor.getName();
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean isType() {
+        return false;
+    }
+
+    @Override
+    public ClassDeclaration declaringType() {
+        return new JavassistClassDeclaration(ctConstructor.getDeclaringClass(), typeSolver);
+    }
+
+    @Override
+    public int getNumberOfParams() {
+        try {
+            return ctConstructor.getParameterTypes().length;
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ParameterDeclaration getParam(int i) {
+        try {
+            boolean variadic = false;
+            if ((ctConstructor.getModifiers() & javassist.Modifier.VARARGS) > 0) {
+                variadic = i == (ctConstructor.getParameterTypes().length - 1);
+            }
+            if (ctConstructor.getGenericSignature() != null) {
+                SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctConstructor.getGenericSignature());
+                SignatureAttribute.Type signatureType = methodSignature.getParameterTypes()[i];
+                return new JavassistParameterDeclaration(JavassistUtils.signatureTypeToType(signatureType, typeSolver, this), typeSolver, variadic);
+            } else {
+                return new JavassistParameterDeclaration(ctConstructor.getParameterTypes()[i], typeSolver, variadic);
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (BadBytecode badBytecode) {
+            throw new RuntimeException(badBytecode);
+        }
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        try {
+            if (ctConstructor.getGenericSignature() == null) {
+                return Collections.emptyList();
+            }
+            SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctConstructor.getGenericSignature());
+            return Arrays.stream(methodSignature.getTypeParameters()).map((jasTp) -> new JavassistTypeParameter(jasTp, this, typeSolver)).collect(Collectors.toList());
+        } catch (BadBytecode badBytecode) {
+            throw new RuntimeException(badBytecode);
+        }
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return JavassistFactory.modifiersToAccessLevel(ctConstructor.getModifiers());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java
new file mode 100644
index 0000000..234bf6e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+import javassist.bytecode.AccessFlag;
+import javassist.bytecode.SyntheticAttribute;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistEnumDeclaration extends AbstractTypeDeclaration implements EnumDeclaration {
+
+    private CtClass ctClass;
+    private TypeSolver typeSolver;
+    private JavassistTypeDeclarationAdapter javassistTypeDeclarationAdapter;
+
+    public JavassistEnumDeclaration(CtClass ctClass, TypeSolver typeSolver) {
+        if (ctClass == null) {
+            throw new IllegalArgumentException();
+        }
+        if (!ctClass.isEnum()) {
+            throw new IllegalArgumentException("Trying to instantiate a JavassistEnumDeclaration with something which is not an enum: " + ctClass.toString());
+        }
+        this.ctClass = ctClass;
+        this.typeSolver = typeSolver;
+        this.javassistTypeDeclarationAdapter = new JavassistTypeDeclarationAdapter(ctClass, typeSolver);
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return JavassistFactory.modifiersToAccessLevel(ctClass.getModifiers());
+    }
+
+    @Override
+    public String getPackageName() {
+        return ctClass.getPackageName();
+    }
+
+    @Override
+    public String getClassName() {
+        String name = ctClass.getName().replace('$', '.');
+        if (getPackageName() != null) {
+            return name.substring(getPackageName().length() + 1, name.length());
+        }
+        return name;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return ctClass.getName().replace('$', '.');
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        // Direct ancestors of an enum are java.lang.Enum and interfaces
+        List<ReferenceType> ancestors = new LinkedList<>();
+
+        try {
+            CtClass superClass = ctClass.getSuperclass();
+
+            if (superClass != null) {
+                Type superClassTypeUsage = JavassistFactory.typeUsageFor(superClass, typeSolver);
+
+                if (superClassTypeUsage.isReferenceType()) {
+                    ancestors.add(superClassTypeUsage.asReferenceType());
+                }
+            }
+
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                Type interfazeTypeUsage = JavassistFactory.typeUsageFor(interfaze, typeSolver);
+
+                if (interfazeTypeUsage.isReferenceType()) {
+                    ancestors.add(interfazeTypeUsage.asReferenceType());
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException("Ancestor not found for " + ctClass.getName() + ".", e);
+        }
+
+        return ancestors;
+    }
+
+    @Override
+    public FieldDeclaration getField(String name) {
+        Optional<FieldDeclaration> field = javassistTypeDeclarationAdapter.getDeclaredFields().stream().filter(f -> f.getName().equals(name)).findFirst();
+
+        return field.orElseThrow(() -> new RuntimeException("Field " + name + " does not exist in " + ctClass.getName() + "."));
+    }
+
+    @Override
+    public boolean hasField(String name) {
+        return javassistTypeDeclarationAdapter.getDeclaredFields().stream().anyMatch(f -> f.getName().equals(name));
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        return javassistTypeDeclarationAdapter.getDeclaredFields();
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return javassistTypeDeclarationAdapter.getDeclaredMethods();
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName() {
+        String[] nameElements = ctClass.getSimpleName().replace('$', '.').split("\\.");
+        return nameElements[nameElements.length - 1];
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return javassistTypeDeclarationAdapter.getTypeParameters();
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return javassistTypeDeclarationAdapter.containerType();
+    }
+
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly) {
+        List<MethodDeclaration> candidates = new ArrayList<>();
+        Predicate<CtMethod> staticOnlyCheck = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
+        for (CtMethod method : ctClass.getDeclaredMethods()) {
+            boolean isSynthetic = method.getMethodInfo().getAttribute(SyntheticAttribute.tag) != null;
+            boolean isNotBridge = (method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0;
+            if (method.getName().equals(name) && !isSynthetic && isNotBridge && staticOnlyCheck.test(method)) {
+                candidates.add(new JavassistMethodDeclaration(method, typeSolver));
+            }
+        }
+
+        try {
+            CtClass superClass = ctClass.getSuperclass();
+            if (superClass != null) {
+                SymbolReference<MethodDeclaration> ref = new JavassistClassDeclaration(superClass, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
+                if (ref.isSolved()) {
+                    candidates.add(ref.getCorrespondingDeclaration());
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        return MethodResolutionLogic.findMostApplicable(candidates, name, argumentsTypes, typeSolver);
+    }
+
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver, Context invokationContext, List<Type> typeParameterValues) {
+        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
+    }
+
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        try {
+            /*
+            Get all internal types of the current class and get their corresponding ReferenceTypeDeclaration.
+            Finally, return them in a Set.
+             */
+            return Arrays.stream(ctClass.getDeclaredClasses()).map(itype -> JavassistFactory.toTypeDeclaration(itype, typeSolver)).collect(Collectors.toSet());
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ReferenceTypeDeclaration getInternalType(String name) {
+        /*
+        The name of the ReferenceTypeDeclaration could be composed on the internal class and the outer class, e.g. A$B. That's why we search the internal type in the ending part.
+        In case the name is composed of the internal type only, i.e. f.getName() returns B, it will also works.
+         */
+        Optional<ReferenceTypeDeclaration> type =
+                this.internalTypes().stream().filter(f -> f.getName().endsWith(name)).findFirst();
+        return type.orElseThrow(() ->
+                new UnsolvedSymbolException("Internal type not found: " + name));
+    }
+
+    @Override
+    public boolean hasInternalType(String name) {
+        /*
+        The name of the ReferenceTypeDeclaration could be composed on the internal class and the outer class, e.g. A$B. That's why we search the internal type in the ending part.
+        In case the name is composed of the internal type only, i.e. f.getName() returns B, it will also works.
+         */
+        return this.internalTypes().stream().anyMatch(f -> f.getName().endsWith(name));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java
new file mode 100644
index 0000000..fc16528
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistFactory.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.AccessLevel;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+import javassist.CtClass;
+import javassist.NotFoundException;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistFactory {
+
+  public static Type typeUsageFor(CtClass ctClazz, TypeSolver typeSolver) {
+    try {
+      if (ctClazz.isArray()) {
+        return new ArrayType(typeUsageFor(ctClazz.getComponentType(), typeSolver));
+      } else if (ctClazz.isPrimitive()) {
+        if (ctClazz.getName().equals("void")) {
+          return VoidType.INSTANCE;
+        } else {
+          return PrimitiveType.byName(ctClazz.getName());
+        }
+      } else {
+        if (ctClazz.isInterface()) {
+          return new ReferenceTypeImpl(new JavassistInterfaceDeclaration(ctClazz, typeSolver),
+              typeSolver);
+        } else if (ctClazz.isEnum()) {
+          return new ReferenceTypeImpl(new JavassistEnumDeclaration(ctClazz, typeSolver),
+              typeSolver);
+        } else {
+          return new ReferenceTypeImpl(new JavassistClassDeclaration(ctClazz, typeSolver),
+              typeSolver);
+        }
+      }
+    } catch (NotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public static ReferenceTypeDeclaration toTypeDeclaration(CtClass ctClazz, TypeSolver typeSolver) {
+    if (ctClazz.isInterface()) {
+      return new JavassistInterfaceDeclaration(ctClazz, typeSolver);
+    } else if (ctClazz.isEnum()) {
+      return new JavassistEnumDeclaration(ctClazz, typeSolver);
+    } else if (ctClazz.isAnnotation()) {
+      throw new UnsupportedOperationException("CtClass of annotation not yet supported");
+    } else if (ctClazz.isArray()) {
+      throw new IllegalArgumentException("This method should not be called passing an array");
+    } else {
+      return new JavassistClassDeclaration(ctClazz, typeSolver);
+    }
+  }
+
+  static AccessLevel modifiersToAccessLevel(final int modifiers) {
+    if (Modifier.isPublic(modifiers)) {
+      return AccessLevel.PUBLIC;
+    } else if (Modifier.isProtected(modifiers)) {
+      return AccessLevel.PROTECTED;
+    } else if (Modifier.isPrivate(modifiers)) {
+      return AccessLevel.PRIVATE;
+    } else {
+      return AccessLevel.PACKAGE_PROTECTED;
+    }
+  }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration.java
new file mode 100644
index 0000000..b3af312
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistFieldDeclaration.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.AccessLevel;
+import com.github.javaparser.symbolsolver.model.declarations.FieldDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import javassist.CtField;
+import javassist.NotFoundException;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistFieldDeclaration implements FieldDeclaration {
+    private CtField ctField;
+    private TypeSolver typeSolver;
+
+    public JavassistFieldDeclaration(CtField ctField, TypeSolver typeSolver) {
+        this.ctField = ctField;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public Type getType() {
+        try {
+            return JavassistFactory.typeUsageFor(ctField.getType(), typeSolver);
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public boolean isStatic() {
+        return Modifier.isStatic(ctField.getModifiers());
+    }
+
+    @Override
+    public String getName() {
+        return ctField.getName();
+    }
+
+    @Override
+    public boolean isField() {
+        return true;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean isType() {
+        return false;
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return JavassistFactory.modifiersToAccessLevel(ctField.getModifiers());
+    }
+
+    @Override
+    public TypeDeclaration declaringType() {
+        return JavassistFactory.toTypeDeclaration(ctField.getDeclaringClass(), typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java
new file mode 100644
index 0000000..9570c33
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+import javassist.bytecode.AccessFlag;
+import javassist.bytecode.SyntheticAttribute;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistInterfaceDeclaration extends AbstractTypeDeclaration implements InterfaceDeclaration {
+
+    private CtClass ctClass;
+    private TypeSolver typeSolver;
+    private JavassistTypeDeclarationAdapter javassistTypeDeclarationAdapter;
+
+    @Override
+    public String toString() {
+        return "JavassistInterfaceDeclaration{" +
+                "ctClass=" + ctClass.getName() +
+                ", typeSolver=" + typeSolver +
+                '}';
+    }
+
+    public JavassistInterfaceDeclaration(CtClass ctClass, TypeSolver typeSolver) {
+        if (!ctClass.isInterface()) {
+            throw new IllegalArgumentException("Not an interface: " + ctClass.getName());
+        }
+        this.ctClass = ctClass;
+        this.typeSolver = typeSolver;
+        this.javassistTypeDeclarationAdapter = new JavassistTypeDeclarationAdapter(ctClass, typeSolver);
+    }
+
+    @Override
+    public List<ReferenceType> getInterfacesExtended() {
+        try {
+            return Arrays.stream(ctClass.getInterfaces()).map(i -> new JavassistInterfaceDeclaration(i, typeSolver))
+                    .map(i -> new ReferenceTypeImpl(i, typeSolver)).collect(Collectors.toList());
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public String getPackageName() {
+        return ctClass.getPackageName();
+    }
+
+    @Override
+    public String getClassName() {
+        String className = ctClass.getName().replace('$', '.');
+        if (getPackageName() != null) {
+            return className.substring(getPackageName().length() + 1, className.length());
+        }
+        return className;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return ctClass.getName().replace('$', '.');
+    }
+
+    @Deprecated
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver,
+                                                    Context invokationContext, List<Type> typeParameterValues) {
+
+        return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
+    }
+
+    @Deprecated
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly) {
+        List<MethodDeclaration> candidates = new ArrayList<>();
+        Predicate<CtMethod> staticOnlyCheck = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
+        for (CtMethod method : ctClass.getDeclaredMethods()) {
+            boolean isSynthetic = method.getMethodInfo().getAttribute(SyntheticAttribute.tag) != null;
+            boolean isNotBridge =  (method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0;
+            if (method.getName().equals(name) && !isSynthetic && isNotBridge && staticOnlyCheck.test(method)) {
+                candidates.add(new JavassistMethodDeclaration(method, typeSolver));
+            }
+        }
+
+        try {
+            CtClass superClass = ctClass.getSuperclass();
+            if (superClass != null) {
+                SymbolReference<MethodDeclaration> ref = new JavassistClassDeclaration(superClass, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
+                if (ref.isSolved()) {
+                    candidates.add(ref.getCorrespondingDeclaration());
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        try {
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                SymbolReference<MethodDeclaration> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveMethod(name, argumentsTypes, staticOnly);
+                if (ref.isSolved()) {
+                    candidates.add(ref.getCorrespondingDeclaration());
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        return MethodResolutionLogic.findMostApplicable(candidates, name, argumentsTypes, typeSolver);
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+      return javassistTypeDeclarationAdapter.getDeclaredFields();
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        List<ReferenceType> ancestors = new ArrayList<>();
+        try {
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                ReferenceType superInterfaze = JavassistFactory.typeUsageFor(interfaze, typeSolver).asReferenceType();
+                ancestors.add(superInterfaze);
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+        ancestors = ancestors.stream().filter(a -> a.getQualifiedName() != Object.class.getCanonicalName())
+                .collect(Collectors.toList());
+        ancestors.add(new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver));
+        return ancestors;
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return Arrays.stream(ctClass.getDeclaredMethods())
+                .map(m -> new JavassistMethodDeclaration(m, typeSolver))
+                .collect(Collectors.toSet());
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        try {
+            for (Object annotationRaw : ctClass.getAnnotations()) {
+                if (annotationRaw.getClass().getCanonicalName().equals(canonicalName)) {
+                    return true;
+                }
+                if (Arrays.stream(annotationRaw.getClass().getInterfaces()).anyMatch(it -> it.getCanonicalName().equals(canonicalName))) {
+                    return true;
+                }
+            }
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+        return false;
+    }
+
+    @Override
+    public String getName() {
+        String[] nameElements = ctClass.getSimpleName().replace('$', '.').split("\\.");
+        return nameElements[nameElements.length - 1];
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return javassistTypeDeclarationAdapter.getTypeParameters();
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return JavassistFactory.modifiersToAccessLevel(ctClass.getModifiers());
+    }
+
+    @Override
+    public InterfaceDeclaration asInterface() {
+        return this;
+    }
+
+
+    @Deprecated
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (CtField field : ctClass.getDeclaredFields()) {
+            if (field.getName().equals(name)) {
+                return SymbolReference.solved(new JavassistFieldDeclaration(field, typeSolver));
+            }
+        }
+
+        try {
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                SymbolReference<? extends ValueDeclaration> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveSymbol(name, typeSolver);
+                if (ref.isSolved()) {
+                    return ref;
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        return SymbolReference.unsolved(ValueDeclaration.class);
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return javassistTypeDeclarationAdapter.containerType();
+    }
+
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        try {
+            /*
+            Get all internal types of the current class and get their corresponding ReferenceTypeDeclaration.
+            Finally, return them in a Set.
+             */
+            return Arrays.stream(ctClass.getDeclaredClasses()).map(itype -> JavassistFactory.toTypeDeclaration(itype, typeSolver)).collect(Collectors.toSet());
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ReferenceTypeDeclaration getInternalType(String name) {
+        /*
+        The name of the ReferenceTypeDeclaration could be composed on the internal class and the outer class, e.g. A$B. That's why we search the internal type in the ending part.
+        In case the name is composed of the internal type only, i.e. f.getName() returns B, it will also works.
+         */
+        Optional<ReferenceTypeDeclaration> type =
+                this.internalTypes().stream().filter(f -> f.getName().endsWith(name)).findFirst();
+        return type.orElseThrow(() ->
+                new UnsolvedSymbolException("Internal type not found: " + name));
+    }
+
+    @Override
+    public boolean hasInternalType(String name) {
+        /*
+        The name of the ReferenceTypeDeclaration could be composed on the internal class and the outer class, e.g. A$B. That's why we search the internal type in the ending part.
+        In case the name is composed of the internal type only, i.e. f.getName() returns B, it will also works.
+         */
+        return this.internalTypes().stream().anyMatch(f -> f.getName().endsWith(name));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java
new file mode 100644
index 0000000..26d087f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+import javassist.bytecode.BadBytecode;
+import javassist.bytecode.SignatureAttribute;
+
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistMethodDeclaration implements MethodDeclaration {
+    private CtMethod ctMethod;
+    private TypeSolver typeSolver;
+
+    public JavassistMethodDeclaration(CtMethod ctMethod, TypeSolver typeSolver) {
+        this.ctMethod = ctMethod;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public boolean isDefaultMethod() {
+        return ctMethod.getDeclaringClass().isInterface() && !isAbstract();
+    }
+
+    @Override
+    public boolean isStatic() {
+        return Modifier.isStatic(ctMethod.getModifiers());
+    }
+
+    @Override
+    public String toString() {
+        return "JavassistMethodDeclaration{" +
+                "ctMethod=" + ctMethod +
+                '}';
+    }
+
+    @Override
+    public String getName() {
+        return ctMethod.getName();
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean isType() {
+        return false;
+    }
+
+    @Override
+    public ReferenceTypeDeclaration declaringType() {
+        if (ctMethod.getDeclaringClass().isInterface()) {
+            return new JavassistInterfaceDeclaration(ctMethod.getDeclaringClass(), typeSolver);
+        } else {
+            return new JavassistClassDeclaration(ctMethod.getDeclaringClass(), typeSolver);
+        }
+    }
+
+    @Override
+    public Type getReturnType() {
+        try {
+            return JavassistFactory.typeUsageFor(ctMethod.getReturnType(), typeSolver);
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    @Override
+    public int getNumberOfParams() {
+        try {
+            return ctMethod.getParameterTypes().length;
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ParameterDeclaration getParam(int i) {
+        try {
+            boolean variadic = false;
+            if ((ctMethod.getModifiers() & javassist.Modifier.VARARGS) > 0) {
+                variadic = i == (ctMethod.getParameterTypes().length - 1);
+            }
+            if (ctMethod.getGenericSignature() != null) {
+                SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctMethod.getGenericSignature());
+                SignatureAttribute.Type signatureType = methodSignature.getParameterTypes()[i];
+                return new JavassistParameterDeclaration(JavassistUtils.signatureTypeToType(signatureType, typeSolver, this), typeSolver, variadic);
+            } else {
+                return new JavassistParameterDeclaration(ctMethod.getParameterTypes()[i], typeSolver, variadic);
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (BadBytecode badBytecode) {
+            throw new RuntimeException(badBytecode);
+        }
+    }
+
+    public MethodUsage getUsage(Node node) {
+        throw new UnsupportedOperationException();
+    }
+
+    public MethodUsage resolveTypeVariables(Context context, List<Type> parameterTypes) {
+        return new MethodDeclarationCommonLogic(this, typeSolver).resolveTypeVariables(context, parameterTypes);
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return Modifier.isAbstract(ctMethod.getModifiers());
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        try {
+            if (ctMethod.getGenericSignature() == null) {
+                return Collections.emptyList();
+            }
+            SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctMethod.getGenericSignature());
+            return Arrays.stream(methodSignature.getTypeParameters()).map((jasTp) -> new JavassistTypeParameter(jasTp, this, typeSolver)).collect(Collectors.toList());
+        } catch (BadBytecode badBytecode) {
+            throw new RuntimeException(badBytecode);
+        }
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration.java
new file mode 100644
index 0000000..2ec4eb6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistParameterDeclaration.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.ParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import javassist.CtClass;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistParameterDeclaration implements ParameterDeclaration {
+    private Type type;
+    private TypeSolver typeSolver;
+    private boolean variadic;
+
+    public JavassistParameterDeclaration(CtClass type, TypeSolver typeSolver, boolean variadic) {
+        this(JavassistFactory.typeUsageFor(type, typeSolver), typeSolver, variadic);
+    }
+
+    public JavassistParameterDeclaration(Type type, TypeSolver typeSolver, boolean variadic) {
+        this.type = type;
+        this.typeSolver = typeSolver;
+        this.variadic = variadic;
+    }
+
+    @Override
+    public String toString() {
+        return "JavassistParameterDeclaration{" +
+                "type=" + type +
+                ", typeSolver=" + typeSolver +
+                ", variadic=" + variadic +
+                '}';
+    }
+
+    @Override
+    public String getName() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isField() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isParameter() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isVariadic() {
+        return variadic;
+    }
+
+    @Override
+    public boolean isType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Type getType() {
+        return type;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java
new file mode 100644
index 0000000..7ea5df0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import javassist.CtClass;
+import javassist.NotFoundException;
+import javassist.bytecode.BadBytecode;
+import javassist.bytecode.SignatureAttribute;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistTypeDeclarationAdapter {
+
+  private CtClass ctClass;
+  private TypeSolver typeSolver;
+
+  public JavassistTypeDeclarationAdapter(CtClass ctClass, TypeSolver typeSolver) {
+    this.ctClass = ctClass;
+    this.typeSolver = typeSolver;
+  }
+
+  public Set<MethodDeclaration> getDeclaredMethods() {
+    return Arrays.stream(ctClass.getDeclaredMethods())
+        .map(m -> new JavassistMethodDeclaration(m, typeSolver)).collect(Collectors.toSet());
+  }
+
+  public List<ConstructorDeclaration> getConstructors() {
+    return Arrays.stream(ctClass.getConstructors())
+        .map(m -> new JavassistConstructorDeclaration(m, typeSolver)).collect(Collectors.toList());
+  }
+
+  public List<FieldDeclaration> getDeclaredFields() {
+    List<FieldDeclaration> fieldDecls = new ArrayList<>();
+    collectDeclaredFields(ctClass, fieldDecls);
+    return fieldDecls;
+  }
+
+  private void collectDeclaredFields(CtClass ctClass, List<FieldDeclaration> fieldDecls) {
+    if (ctClass != null) {
+      Arrays.stream(ctClass.getDeclaredFields())
+          .forEach(f -> fieldDecls.add(new JavassistFieldDeclaration(f, typeSolver)));
+      try {
+        collectDeclaredFields(ctClass.getSuperclass(), fieldDecls);
+      } catch (NotFoundException e) {
+        // We'll stop here
+      }
+    }
+  }
+
+  public List<TypeParameterDeclaration> getTypeParameters() {
+    if (null == ctClass.getGenericSignature()) {
+      return Collections.emptyList();
+    } else {
+      try {
+        SignatureAttribute.ClassSignature classSignature =
+            SignatureAttribute.toClassSignature(ctClass.getGenericSignature());
+        return Arrays.<SignatureAttribute.TypeParameter>stream(classSignature.getParameters())
+            .map((tp) -> new JavassistTypeParameter(tp, JavassistFactory.toTypeDeclaration(ctClass, typeSolver), typeSolver))
+            .collect(Collectors.toList());
+      } catch (BadBytecode badBytecode) {
+        throw new RuntimeException(badBytecode);
+      }
+    }
+  }
+
+  public Optional<ReferenceTypeDeclaration> containerType() {
+    try {
+      return ctClass.getDeclaringClass() == null ?
+          Optional.empty() :
+          Optional.of(JavassistFactory.toTypeDeclaration(ctClass.getDeclaringClass(), typeSolver));
+    } catch (NotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java
new file mode 100644
index 0000000..81348dd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeParameter.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParametrizable;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import javassist.bytecode.SignatureAttribute;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavassistTypeParameter implements TypeParameterDeclaration {
+
+    private SignatureAttribute.TypeParameter wrapped;
+    private TypeSolver typeSolver;
+    private TypeParametrizable container;
+
+    public JavassistTypeParameter(SignatureAttribute.TypeParameter wrapped, TypeParametrizable container, TypeSolver typeSolver) {
+        this.wrapped = wrapped;
+        this.typeSolver = typeSolver;
+        this.container = container;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof TypeParameterDeclaration)) return false;
+
+        TypeParameterDeclaration that = (TypeParameterDeclaration) o;
+
+        if (!getQualifiedName().equals(that.getQualifiedName())) {
+            return false;
+        }
+        if (declaredOnType() != that.declaredOnType()) {
+            return false;
+        }
+        if (declaredOnMethod() != that.declaredOnMethod()) {
+            return false;
+        }
+        // TODO check bounds
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "JavassistTypeParameter{" +
+                wrapped.getName()
+                + '}';
+    }
+
+    @Override
+    public String getName() {
+        return wrapped.getName();
+    }
+
+    @Override
+    public String getContainerQualifiedName() {
+        if (this.container instanceof ReferenceTypeDeclaration) {
+            return ((ReferenceTypeDeclaration) this.container).getQualifiedName();
+        } else if (this.container instanceof MethodLikeDeclaration) {
+            return ((MethodLikeDeclaration) this.container).getQualifiedName();
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getContainerId() {
+        return getContainerQualifiedName();
+    }
+
+    @Override
+    public TypeParametrizable getContainer() {
+        return this.container;
+    }
+
+    @Override
+    public List<TypeParameterDeclaration.Bound> getBounds(TypeSolver typeSolver) {
+        List<Bound> bounds = new ArrayList<>();
+        if (wrapped.getClassBound() != null && !wrapped.getClassBound().toString().equals(Object.class.getCanonicalName())) {
+            throw new UnsupportedOperationException(wrapped.getClassBound().toString());
+        }
+        for (SignatureAttribute.ObjectType ot : wrapped.getInterfaceBound()) {
+            throw new UnsupportedOperationException(ot.toString());
+        }
+        return bounds;
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        if (container instanceof ReferenceTypeDeclaration) {
+            return Optional.of((ReferenceTypeDeclaration) container);
+        }
+        return Optional.empty();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java
new file mode 100644
index 0000000..3ab7ba0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.javassistmodel;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParametrizable;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+import javassist.bytecode.BadBytecode;
+import javassist.bytecode.SignatureAttribute;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+class JavassistUtils {
+
+    static Optional<MethodUsage> getMethodUsage(CtClass ctClass, String name, List<Type> argumentsTypes, TypeSolver typeSolver, Context invokationContext) {
+        // TODO avoid bridge and synthetic methods
+        for (CtMethod method : ctClass.getDeclaredMethods()) {
+            if (method.getName().equals(name)) {
+                // TODO check typeParametersValues
+                MethodUsage methodUsage = new MethodUsage(new JavassistMethodDeclaration(method, typeSolver));
+                if (argumentsTypes.size() < methodUsage.getNoParams()) {
+                    // this method cannot be a good candidate (except if variadic ?)
+                    continue;
+                }
+                try {
+                    if (method.getGenericSignature() != null) {
+                        SignatureAttribute.MethodSignature classSignature = SignatureAttribute.toMethodSignature(method.getGenericSignature());
+                        List<Type> parametersOfReturnType = parseTypeParameters(classSignature.getReturnType().toString(), typeSolver, invokationContext);
+                        Type newReturnType = methodUsage.returnType();
+                        // consume one parametersOfReturnType at the time
+                        if (!(newReturnType instanceof VoidType)) {
+                            newReturnType = newReturnType.asReferenceType().transformTypeParameters(tp -> parametersOfReturnType.remove(0));
+                        }
+                        methodUsage = methodUsage.replaceReturnType(newReturnType);
+                    }
+                    return Optional.of(methodUsage);
+                } catch (BadBytecode e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+
+        try {
+            CtClass superClass = ctClass.getSuperclass();
+            if (superClass != null) {
+                Optional<MethodUsage> ref = new JavassistClassDeclaration(superClass, typeSolver).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, null);
+                if (ref.isPresent()) {
+                    return ref;
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        try {
+            for (CtClass interfaze : ctClass.getInterfaces()) {
+                Optional<MethodUsage> ref = new JavassistInterfaceDeclaration(interfaze, typeSolver).solveMethodAsUsage(name, argumentsTypes, typeSolver, invokationContext, null);
+                if (ref.isPresent()) {
+                    return ref;
+                }
+            }
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        return Optional.empty();
+    }
+
+    private static List<Type> parseTypeParameters(String signature, TypeSolver typeSolver, Context invokationContext) {
+        String originalSignature = signature;
+        if (signature.contains("<")) {
+            signature = signature.substring(signature.indexOf('<') + 1);
+            if (!signature.endsWith(">")) {
+                throw new IllegalArgumentException();
+            }
+            signature = signature.substring(0, signature.length() - 1);
+            if (signature.contains(",")) {
+                throw new UnsupportedOperationException();
+            }
+            if (signature.contains("<")) {
+                throw new UnsupportedOperationException(originalSignature);
+            }
+            if (signature.contains(">")) {
+                throw new UnsupportedOperationException();
+            }
+            List<Type> types = new ArrayList<>();
+            types.add(new SymbolSolver(typeSolver).solveTypeUsage(signature, invokationContext));
+            return types;
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    static Type signatureTypeToType(SignatureAttribute.Type signatureType, TypeSolver typeSolver, TypeParametrizable typeParametrizable) {
+        if (signatureType instanceof SignatureAttribute.ClassType) {
+            SignatureAttribute.ClassType classType = (SignatureAttribute.ClassType) signatureType;
+            List<Type> typeParameters = classType.getTypeArguments() == null ? Collections.emptyList() : Arrays.stream(classType.getTypeArguments()).map(ta -> typeArgumentToType(ta, typeSolver, typeParametrizable)).collect(Collectors.toList());
+            final String typeName =
+                    classType.getDeclaringClass() != null ?
+                            classType.getDeclaringClass().getName() + "." + classType.getName() :
+                            classType.getName();
+            ReferenceTypeDeclaration typeDeclaration = typeSolver.solveType(
+                    internalNameToCanonicalName(typeName));
+            return new ReferenceTypeImpl(typeDeclaration, typeParameters, typeSolver);
+        } else if (signatureType instanceof SignatureAttribute.TypeVariable) {
+            SignatureAttribute.TypeVariable typeVariableSignature = (SignatureAttribute.TypeVariable)signatureType;
+            Optional<TypeParameterDeclaration> typeParameterDeclarationOpt = typeParametrizable.findTypeParameter(typeVariableSignature.getName());
+            if (!typeParameterDeclarationOpt.isPresent()) {
+                throw new UnsolvedSymbolException("Unable to solve TypeVariable " + typeVariableSignature);
+            }
+            TypeParameterDeclaration typeParameterDeclaration = typeParameterDeclarationOpt.get();
+            return new TypeVariable(typeParameterDeclaration);
+        } else {
+            throw new RuntimeException(signatureType.getClass().getCanonicalName());
+        }
+    }
+
+    private static String internalNameToCanonicalName(String typeName) {
+        return typeName.replaceAll("\\$", ".");
+    }
+
+    private static Type objectTypeArgumentToType(SignatureAttribute.ObjectType typeArgument, TypeSolver typeSolver, TypeParametrizable typeParametrizable) {
+        String typeName = typeArgument.jvmTypeName();
+        Optional<Type> type = getGenericParameterByName(typeName, typeParametrizable);
+        return type.orElseGet(() -> new ReferenceTypeImpl(
+            typeSolver.solveType(internalNameToCanonicalName(typeName)),
+            typeSolver));
+    }
+
+    private static Optional<Type> getGenericParameterByName(String typeName, TypeParametrizable typeParametrizable) {
+        Optional<TypeParameterDeclaration> tp = typeParametrizable.findTypeParameter(typeName);
+        return tp.map(TypeVariable::new);
+    }
+
+    private static Type typeArgumentToType(SignatureAttribute.TypeArgument typeArgument, TypeSolver typeSolver, TypeParametrizable typeParametrizable) {
+        if (typeArgument.isWildcard()) {
+            if (typeArgument.getType() == null) {
+                return Wildcard.UNBOUNDED;
+            } else if (typeArgument.getKind() == '+') {
+                return Wildcard.extendsBound(objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable));
+            } else if (typeArgument.getKind() == '-') {
+                return Wildcard.superBound(objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable));
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        } else {
+            return objectTypeArgumentToType(typeArgument.getType(), typeSolver, typeParametrizable);
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/package-info.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/package-info.java
new file mode 100644
index 0000000..3512f53
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/javassistmodel/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementation of model based on Javassist.
+ */
+package com.github.javaparser.symbolsolver.javassistmodel;
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/model/typesystem/LazyType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/model/typesystem/LazyType.java
new file mode 100644
index 0000000..179c0fb
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/model/typesystem/LazyType.java
@@ -0,0 +1,117 @@
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+
+import java.util.Map;
+import java.util.function.Function;
+
+public class LazyType implements Type {
+    private Type concrete;
+    private Function<Void, Type> provider;
+
+    public LazyType(Function<Void, Type> provider) {
+        this.provider = provider;
+    }
+
+    private Type getType() {
+        if (concrete == null) {
+            concrete = provider.apply(null);
+        }
+        return concrete;
+    }
+
+    @Override
+    public boolean isArray() {
+        return getType().isArray();
+    }
+
+    @Override
+    public int arrayLevel() {
+        return getType().arrayLevel();
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return getType().isPrimitive();
+    }
+
+    @Override
+    public boolean isNull() {
+        return getType().isNull();
+    }
+
+    @Override
+    public boolean isReference() {
+        return getType().isReference();
+    }
+
+    @Override
+    public boolean isReferenceType() {
+        return getType().isReferenceType();
+    }
+
+    @Override
+    public boolean isVoid() {
+        return getType().isVoid();
+    }
+
+    @Override
+    public boolean isTypeVariable() {
+        return getType().isTypeVariable();
+    }
+
+    @Override
+    public boolean isWildcard() {
+        return getType().isArray();
+    }
+
+    @Override
+    public ArrayType asArrayType() {
+        return getType().asArrayType();
+    }
+
+    @Override
+    public ReferenceType asReferenceType() {
+        return getType().asReferenceType();
+    }
+
+    @Override
+    public TypeParameterDeclaration asTypeParameter() {
+        return getType().asTypeParameter();
+    }
+
+    @Override
+    public TypeVariable asTypeVariable() {
+        return getType().asTypeVariable();
+    }
+
+    @Override
+    public PrimitiveType asPrimitive() {
+        return getType().asPrimitive();
+    }
+
+    @Override
+    public Wildcard asWildcard() {
+        return getType().asWildcard();
+    }
+
+    @Override
+    public String describe() {
+        return getType().describe();
+    }
+
+    @Override
+    public Type replaceTypeVariables(TypeParameterDeclaration tp, Type replaced, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        return getType().replaceTypeVariables(tp, replaced, inferredTypes);
+    }
+
+    @Override
+    public Type replaceTypeVariables(TypeParameterDeclaration tp, Type replaced) {
+        return getType().replaceTypeVariables(tp, replaced);
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        return getType().isAssignableBy(other);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
new file mode 100644
index 0000000..8e474fe
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration.Bound;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+// TODO Remove references to typeSolver: it is needed to instantiate other instances of ReferenceTypeUsage
+//      and to get the Object type declaration
+public class ReferenceTypeImpl extends ReferenceType {
+
+    public static ReferenceType undeterminedParameters(ReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver) {
+        return new ReferenceTypeImpl(typeDeclaration, typeDeclaration.getTypeParameters().stream().map(
+                tp -> new TypeVariable(tp)
+        ).collect(Collectors.toList()), typeSolver);
+    }
+
+    @Override
+    protected ReferenceType create(ReferenceTypeDeclaration typeDeclaration, List<Type> typeParametersCorrected, TypeSolver typeSolver) {
+        return new ReferenceTypeImpl(typeDeclaration, typeParametersCorrected, typeSolver);
+    }
+
+    @Override
+    protected ReferenceType create(ReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver) {
+        return new ReferenceTypeImpl(typeDeclaration, typeSolver);
+    }
+
+    public ReferenceTypeImpl(ReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver) {
+        super(typeDeclaration, typeSolver);
+    }
+
+    public ReferenceTypeImpl(ReferenceTypeDeclaration typeDeclaration, List<Type> typeParameters, TypeSolver typeSolver) {
+        super(typeDeclaration, typeParameters, typeSolver);
+    }
+
+    @Override
+    public TypeParameterDeclaration asTypeParameter() {
+        if (this.typeDeclaration instanceof JavaParserTypeVariableDeclaration) {
+            JavaParserTypeVariableDeclaration javaParserTypeVariableDeclaration = (JavaParserTypeVariableDeclaration) this.typeDeclaration;
+            return javaParserTypeVariableDeclaration.asTypeParameter();
+        }
+        throw new UnsupportedOperationException(this.typeDeclaration.getClass().getCanonicalName());
+    }
+
+    /**
+     * This method checks if ThisType t = new OtherType() would compile.
+     */
+    @Override
+    public boolean isAssignableBy(Type other) {
+        if (other instanceof NullType) {
+            return !this.isPrimitive();
+        }
+        // everything is assignable to Object except void
+        if (!other.isVoid() && this.getQualifiedName().equals(Object.class.getCanonicalName())) {
+            return true;
+        }
+        // consider boxing
+        if (other.isPrimitive()) {
+            if (this.getQualifiedName().equals(Object.class.getCanonicalName())) {
+                return true;
+            } else {
+                // Check if 'other' can be boxed to match this type
+                if (isCorrespondingBoxingType(other.describe())) return true;
+
+                // Resolve the boxed type and check if it can be assigned via widening reference conversion
+                SymbolReference<ReferenceTypeDeclaration> type = typeSolver.tryToSolveType(other.asPrimitive().getBoxTypeQName());
+                return type.getCorrespondingDeclaration().canBeAssignedTo(super.typeDeclaration);
+            }
+        }
+        if (other instanceof LambdaArgumentTypePlaceholder) {
+            return this.getTypeDeclaration().hasAnnotation(FunctionalInterface.class.getCanonicalName());
+        } else if (other instanceof ReferenceTypeImpl) {
+            ReferenceTypeImpl otherRef = (ReferenceTypeImpl) other;
+            if (compareConsideringTypeParameters(otherRef)) {
+                return true;
+            }
+            for (ReferenceType otherAncestor : otherRef.getAllAncestors()) {
+                if (compareConsideringTypeParameters(otherAncestor)) {
+                    return true;
+                }
+            }
+            return false;
+        } else if (other.isTypeVariable()) {
+            for (Bound bound : other.asTypeVariable().asTypeParameter().getBounds(typeSolver)) {
+                if (bound.isExtends()) {
+                    if (this.isAssignableBy(bound.getType())) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        } else if (other.isConstraint()){
+            return isAssignableBy(other.asConstraintType().getBound());
+        } else if (other.isWildcard()) {
+            if (this.getQualifiedName().equals(Object.class.getCanonicalName())) {
+                return true;
+            } else if (other.asWildcard().isExtends()) {
+                return isAssignableBy(other.asWildcard().getBoundedType());
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public Set<MethodUsage> getDeclaredMethods() {
+        // TODO replace variables
+        Set<MethodUsage> methods = new HashSet<>();
+        for (MethodDeclaration methodDeclaration : getTypeDeclaration().getDeclaredMethods()) {
+            MethodUsage methodUsage = new MethodUsage(methodDeclaration);
+            methods.add(methodUsage);
+        }
+        return methods;
+    }
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/MyObjectProvider.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/MyObjectProvider.java
new file mode 100644
index 0000000..88ee43b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/MyObjectProvider.java
@@ -0,0 +1,36 @@
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.logic.ObjectProvider;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class MyObjectProvider implements ObjectProvider {
+
+    public static final MyObjectProvider INSTANCE = new MyObjectProvider();
+
+    private MyObjectProvider() {
+        // prevent instantiation
+    }
+
+    @Override
+    public ReferenceType object() {
+        return new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, new ReflectionTypeSolver()), new ReflectionTypeSolver());
+    }
+
+    @Override
+    public ReferenceType byName(String qualifiedName) {
+        TypeSolver typeSolver = new ReflectionTypeSolver();
+        ReferenceTypeDeclaration typeDeclaration = typeSolver.solveType(qualifiedName);
+        if (!typeDeclaration.getTypeParameters().isEmpty()) {
+            throw new UnsupportedOperationException();
+        }
+        return new ReferenceTypeImpl(typeDeclaration, typeSolver);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java
new file mode 100644
index 0000000..7ed5bcc
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java
@@ -0,0 +1,190 @@
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
+import com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.typesystem.NullType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.TypeVariable;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+class ReflectionClassAdapter {
+
+    private Class<?> clazz;
+    private TypeSolver typeSolver;
+    private ReferenceTypeDeclaration typeDeclaration;
+
+    public ReflectionClassAdapter(Class<?> clazz, TypeSolver typeSolver, ReferenceTypeDeclaration typeDeclaration) {
+        this.clazz = clazz;
+        this.typeSolver = typeSolver;
+        this.typeDeclaration = typeDeclaration;
+    }
+
+    public ReferenceTypeImpl getSuperClass() {
+        if (clazz.getGenericSuperclass() == null) {
+            return null;
+        }
+        java.lang.reflect.Type superType = clazz.getGenericSuperclass();
+        if (superType instanceof ParameterizedType) {
+            ParameterizedType parameterizedType = (ParameterizedType) superType;
+            List<Type> typeParameters = Arrays.stream(parameterizedType.getActualTypeArguments())
+                    .map((t) -> ReflectionFactory.typeUsageFor(t, typeSolver))
+                    .collect(Collectors.toList());
+            return new ReferenceTypeImpl(new ReflectionClassDeclaration(clazz.getSuperclass(), typeSolver), typeParameters, typeSolver);
+        }
+        return new ReferenceTypeImpl(new ReflectionClassDeclaration(clazz.getSuperclass(), typeSolver), typeSolver);
+    }
+
+    public List<ReferenceType> getInterfaces() {
+        List<ReferenceType> interfaces = new ArrayList<>();
+        for (java.lang.reflect.Type superInterface : clazz.getGenericInterfaces()) {
+            if (superInterface instanceof ParameterizedType) {
+                ParameterizedType parameterizedType = (ParameterizedType) superInterface;
+                List<Type> typeParameters = Arrays.stream(parameterizedType.getActualTypeArguments())
+                        .map((t) -> ReflectionFactory.typeUsageFor(t, typeSolver))
+                        .collect(Collectors.toList());
+                interfaces.add(new ReferenceTypeImpl(new ReflectionInterfaceDeclaration((Class<?>) ((ParameterizedType) superInterface).getRawType(), typeSolver), typeParameters, typeSolver));
+            } else {
+                interfaces.add(new ReferenceTypeImpl(new ReflectionInterfaceDeclaration((Class<?>) superInterface, typeSolver), typeSolver));
+            }
+        }
+        return interfaces;
+    }
+
+    public List<ReferenceType> getAncestors() {
+        List<ReferenceType> ancestors = new LinkedList<>();
+        if (getSuperClass() != null) {
+            ReferenceTypeImpl superClass = getSuperClass();
+            ancestors.add(superClass);
+        } else {
+            ReferenceTypeImpl object = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
+            ancestors.add(object);
+        }
+        ancestors.addAll(getInterfaces());
+        for (int i = 0; i < ancestors.size(); i++) {
+            ReferenceType ancestor = ancestors.get(i);
+            if (ancestor.hasName() && ancestor.getQualifiedName().equals(Object.class.getCanonicalName())) {
+                ancestors.remove(i);
+                i--;
+            }
+        }
+        return ancestors;
+    }
+
+    public FieldDeclaration getField(String name) {
+        for (Field field : clazz.getDeclaredFields()) {
+            if (field.getName().equals(name)) {
+                return new ReflectionFieldDeclaration(field, typeSolver);
+            }
+        }
+        for (ReferenceType ancestor : typeDeclaration.getAllAncestors()) {
+            if (ancestor.getTypeDeclaration().hasField(name)) {
+                ReflectionFieldDeclaration reflectionFieldDeclaration = (ReflectionFieldDeclaration) ancestor.getTypeDeclaration().getField(name);
+                return reflectionFieldDeclaration.replaceType(ancestor.getFieldType(name).get());
+            }
+        }
+        throw new UnsolvedSymbolException(name, "Field in " + this);
+    }
+
+    public boolean hasField(String name) {
+        for (Field field : clazz.getDeclaredFields()) {
+            if (field.getName().equals(name)) {
+                return true;
+            }
+        }
+        ReferenceTypeImpl superclass = getSuperClass();
+        if (superclass == null) {
+            return false;
+        } else {
+            return superclass.getTypeDeclaration().hasField(name);
+        }
+    }
+
+    public List<FieldDeclaration> getAllFields() {
+        ArrayList<FieldDeclaration> fields = new ArrayList<>();
+        for (Field field : clazz.getDeclaredFields()) {
+            fields.add(new ReflectionFieldDeclaration(field, typeSolver));
+        }
+        for (ReferenceType ancestor : typeDeclaration.getAllAncestors()) {
+            fields.addAll(ancestor.getTypeDeclaration().getAllFields());
+        }
+        return fields;
+    }
+
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return Arrays.stream(clazz.getDeclaredMethods())
+                .filter(m -> !m.isSynthetic() && !m.isBridge())
+                .map(m -> new ReflectionMethodDeclaration(m, typeSolver))
+                .collect(Collectors.toSet());
+    }
+
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        List<TypeParameterDeclaration> params = new ArrayList<>();
+        for (TypeVariable<?> tv : this.clazz.getTypeParameters()) {
+            params.add(new ReflectionTypeParameter(tv, true, typeSolver));
+        }
+        return params;
+    }
+
+    public boolean isAssignableBy(Type type) {
+        if (type instanceof NullType) {
+            return true;
+        }
+        if (type instanceof LambdaArgumentTypePlaceholder) {
+            return isFunctionalInterface();
+        }
+        if (type.isArray()) {
+            return false;
+        }
+        if (type.isPrimitive()) {
+            return false;
+        }
+        if (type.describe().equals(typeDeclaration.getQualifiedName())) {
+            return true;
+        }
+        if (type instanceof ReferenceTypeImpl) {
+            ReferenceTypeImpl otherTypeDeclaration = (ReferenceTypeImpl) type;
+            return otherTypeDeclaration.getTypeDeclaration().canBeAssignedTo(typeDeclaration);
+        }
+
+        return false;
+    }
+
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        for (Annotation a : clazz.getDeclaredAnnotations()) {
+            if (a.annotationType().getCanonicalName().equals(canonicalName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private final boolean isFunctionalInterface() {
+        return FunctionalInterfaceLogic.getFunctionalMethod(typeDeclaration).isPresent();
+    }
+
+    public List<ConstructorDeclaration> getConstructors() {
+        return Arrays.stream(clazz.getConstructors())
+                .map(m -> new ReflectionConstructorDeclaration(m, typeSolver))
+                .collect(Collectors.toList());
+    }
+    
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        Class<?> declaringClass = clazz.getDeclaringClass();
+        return declaringClass == null ?
+                Optional.empty() :
+                Optional.of(ReflectionFactory.typeDeclarationFor(declaringClass, typeSolver));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration.java
new file mode 100644
index 0000000..c8d920e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassDeclaration.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
+import com.github.javaparser.symbolsolver.javaparsermodel.contexts.ContextHelper;
+import com.github.javaparser.symbolsolver.logic.AbstractClassDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.comparators.MethodComparator;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionClassDeclaration extends AbstractClassDeclaration {
+
+    ///
+    /// Fields
+    ///
+
+    private Class<?> clazz;
+    private TypeSolver typeSolver;
+    private ReflectionClassAdapter reflectionClassAdapter;
+
+    ///
+    /// Constructors
+    ///
+
+    public ReflectionClassDeclaration(Class<?> clazz, TypeSolver typeSolver) {
+        if (clazz == null) {
+            throw new IllegalArgumentException("Class should not be null");
+        }
+        if (clazz.isInterface()) {
+            throw new IllegalArgumentException("Class should not be an interface");
+        }
+        if (clazz.isPrimitive()) {
+            throw new IllegalArgumentException("Class should not represent a primitive class");
+        }
+        if (clazz.isArray()) {
+            throw new IllegalArgumentException("Class should not be an array");
+        }
+        if (clazz.isEnum()) {
+            throw new IllegalArgumentException("Class should not be an enum");
+        }
+        this.clazz = clazz;
+        this.typeSolver = typeSolver;
+        this.reflectionClassAdapter = new ReflectionClassAdapter(clazz, typeSolver, this);
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return reflectionClassAdapter.getDeclaredMethods();
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        return reflectionClassAdapter.getAncestors();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ReflectionClassDeclaration that = (ReflectionClassDeclaration) o;
+
+        if (!clazz.getCanonicalName().equals(that.clazz.getCanonicalName())) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return clazz.hashCode();
+    }
+
+
+    @Override
+    public String getPackageName() {
+        if (clazz.getPackage() != null) {
+            return clazz.getPackage().getName();
+        }
+        return null;
+    }
+
+    @Override
+    public String getClassName() {
+        String canonicalName = clazz.getCanonicalName();
+        if (canonicalName != null && getPackageName() != null) {
+            return canonicalName.substring(getPackageName().length() + 1, canonicalName.length());
+        }
+        return null;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return clazz.getCanonicalName();
+    }
+
+    @Deprecated
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> argumentsTypes, boolean staticOnly) {
+        List<MethodDeclaration> methods = new ArrayList<>();
+        Predicate<Method> staticFilter = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
+        for (Method method : Arrays.stream(clazz.getDeclaredMethods()).filter((m) -> m.getName().equals(name)).filter(staticFilter)
+                                    .sorted(new MethodComparator()).collect(Collectors.toList())) {
+            if (method.isBridge() || method.isSynthetic()) continue;
+            MethodDeclaration methodDeclaration = new ReflectionMethodDeclaration(method, typeSolver);
+            methods.add(methodDeclaration);
+        }
+        if (getSuperClass() != null) {
+            ClassDeclaration superClass = (ClassDeclaration) getSuperClass().getTypeDeclaration();
+            SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(superClass, name, argumentsTypes, staticOnly, typeSolver);
+            if (ref.isSolved()) {
+                methods.add(ref.getCorrespondingDeclaration());
+            }
+        }
+        for (ReferenceType interfaceDeclaration : getInterfaces()) {
+            SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(interfaceDeclaration.getTypeDeclaration(), name, argumentsTypes, staticOnly, typeSolver);
+            if (ref.isSolved()) {
+                methods.add(ref.getCorrespondingDeclaration());
+            }
+        }
+        return MethodResolutionLogic.findMostApplicable(methods, name, argumentsTypes, typeSolver);
+    }
+
+    @Override
+    public String toString() {
+        return "ReflectionClassDeclaration{" +
+                "clazz=" + getId() +
+                '}';
+    }
+
+    public Type getUsage(Node node) {
+
+        return new ReferenceTypeImpl(this, typeSolver);
+    }
+
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver, Context invokationContext, List<Type> typeParameterValues) {
+        List<MethodUsage> methods = new ArrayList<>();
+        for (Method method : Arrays.stream(clazz.getDeclaredMethods()).filter((m) -> m.getName().equals(name)).sorted(new MethodComparator()).collect(Collectors.toList())) {
+            if (method.isBridge() || method.isSynthetic()) continue;
+            MethodDeclaration methodDeclaration = new ReflectionMethodDeclaration(method, typeSolver);
+            MethodUsage methodUsage = new MethodUsage(methodDeclaration);
+            for (int i = 0; i < getTypeParameters().size() && i < typeParameterValues.size(); i++) {
+                TypeParameterDeclaration tpToReplace = getTypeParameters().get(i);
+                Type newValue = typeParameterValues.get(i);
+                methodUsage = methodUsage.replaceTypeParameter(tpToReplace, newValue);
+            }
+            methods.add(methodUsage);
+        }
+        if (getSuperClass() != null) {
+            ClassDeclaration superClass = (ClassDeclaration) getSuperClass().getTypeDeclaration();
+            Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(superClass, name, argumentsTypes, typeSolver, invokationContext, typeParameterValues);
+            if (ref.isPresent()) {
+                methods.add(ref.get());
+            }
+        }
+        for (ReferenceType interfaceDeclaration : getInterfaces()) {
+            Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(interfaceDeclaration.getTypeDeclaration(), name, argumentsTypes, typeSolver, invokationContext, typeParameterValues);
+            if (ref.isPresent()) {
+                methods.add(ref.get());
+            }
+        }
+        Optional<MethodUsage> ref = MethodResolutionLogic.findMostApplicableUsage(methods, name, argumentsTypes, typeSolver);
+        return ref;
+    }
+
+    @Override
+    public boolean canBeAssignedTo(ReferenceTypeDeclaration other) {
+        if (other instanceof LambdaArgumentTypePlaceholder) {
+            return isFunctionalInterface();
+        }
+        if (other.getQualifiedName().equals(getQualifiedName())) {
+            return true;
+        }
+        if (this.clazz.getSuperclass() != null
+                && new ReflectionClassDeclaration(clazz.getSuperclass(), typeSolver).canBeAssignedTo(other)) {
+            return true;
+        }
+        for (Class<?> interfaze : clazz.getInterfaces()) {
+            if (new ReflectionInterfaceDeclaration(interfaze, typeSolver).canBeAssignedTo(other)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        return reflectionClassAdapter.isAssignableBy(type);
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return false;
+    }
+
+    @Override
+    public FieldDeclaration getField(String name) {
+        return reflectionClassAdapter.getField(name);
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        return reflectionClassAdapter.getAllFields();
+    }
+
+    @Deprecated
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (Field field : clazz.getFields()) {
+            if (field.getName().equals(name)) {
+                return SymbolReference.solved(new ReflectionFieldDeclaration(field, typeSolver));
+            }
+        }
+        return SymbolReference.unsolved(ValueDeclaration.class);
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        return reflectionClassAdapter.hasDirectlyAnnotation(canonicalName);
+    }
+
+    @Override
+    public boolean hasField(String name) {
+        return reflectionClassAdapter.hasField(name);
+    }
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return isAssignableBy(new ReferenceTypeImpl(other, typeSolver));
+    }
+
+    @Override
+    public String getName() {
+        return clazz.getSimpleName();
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean isType() {
+        return true;
+    }
+
+    @Override
+    public boolean isClass() {
+        return !clazz.isInterface();
+    }
+
+    @Override
+    public ReferenceTypeImpl getSuperClass() {
+        return reflectionClassAdapter.getSuperClass();
+    }
+
+    @Override
+    public List<ReferenceType> getInterfaces() {
+        return reflectionClassAdapter.getInterfaces();
+    }
+
+    @Override
+    public boolean isInterface() {
+        return clazz.isInterface();
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return reflectionClassAdapter.getTypeParameters();
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return ReflectionFactory.modifiersToAccessLevel(this.clazz.getModifiers());
+    }
+
+    @Override
+    public List<ConstructorDeclaration> getConstructors() {
+        return reflectionClassAdapter.getConstructors();
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return reflectionClassAdapter.containerType();
+    }
+    
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        return Arrays.stream(this.clazz.getDeclaredClasses())
+                .map(ic -> ReflectionFactory.typeDeclarationFor(ic, typeSolver))
+                .collect(Collectors.toSet());
+    }
+
+    ///
+    /// Protected methods
+    ///
+
+    @Override
+    protected ReferenceType object() {
+        return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration.java
new file mode 100644
index 0000000..0e7b19e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionConstructorDeclaration.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Fred Lefévère-Laoide
+ */
+public class ReflectionConstructorDeclaration implements ConstructorDeclaration {
+
+    private Constructor<?> constructor;
+    private TypeSolver typeSolver;
+
+    public ReflectionConstructorDeclaration(Constructor<?> constructor,
+                                            TypeSolver typeSolver) {
+        this.constructor = constructor;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public ClassDeclaration declaringType() {
+        return new ReflectionClassDeclaration(constructor.getDeclaringClass(), typeSolver);
+    }
+
+    @Override
+    public int getNumberOfParams() {
+        return constructor.getParameterCount();
+    }
+
+    @Override
+    public ParameterDeclaration getParam(int i) {
+        if (i < 0 || i >= getNumberOfParams()) {
+            throw new IllegalArgumentException(String.format("No param with index %d. Number of params: %d", i, getNumberOfParams()));
+        }
+        boolean variadic = false;
+        if (constructor.isVarArgs()) {
+            variadic = i == (constructor.getParameterCount() - 1);
+        }
+        return new ReflectionParameterDeclaration(constructor.getParameterTypes()[i], constructor.getGenericParameterTypes()[i], typeSolver, variadic);
+    }
+
+    @Override
+    public String getName() {
+        return constructor.getName();
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return ReflectionFactory.modifiersToAccessLevel(constructor.getModifiers());
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return Arrays.stream(constructor.getTypeParameters()).map((refTp) -> new ReflectionTypeParameter(refTp, false, typeSolver)).collect(Collectors.toList());
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java
new file mode 100644
index 0000000..0a150e9
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.logic.ConfilictingGenericTypesException;
+import com.github.javaparser.symbolsolver.logic.InferenceContext;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.*;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionEnumDeclaration extends AbstractTypeDeclaration implements EnumDeclaration {
+
+  ///
+  /// Fields
+  ///
+
+  private Class<?> clazz;
+  private TypeSolver typeSolver;
+  private ReflectionClassAdapter reflectionClassAdapter;
+
+  ///
+  /// Constructors
+  ///
+
+  public ReflectionEnumDeclaration(Class<?> clazz, TypeSolver typeSolver) {
+    if (clazz == null) {
+      throw new IllegalArgumentException("Class should not be null");
+    }
+    if (clazz.isInterface()) {
+      throw new IllegalArgumentException("Class should not be an interface");
+    }
+    if (clazz.isPrimitive()) {
+      throw new IllegalArgumentException("Class should not represent a primitive class");
+    }
+    if (clazz.isArray()) {
+      throw new IllegalArgumentException("Class should not be an array");
+    }
+    if (!clazz.isEnum()) {
+      throw new IllegalArgumentException("Class should be an enum");
+    }
+    this.clazz = clazz;
+    this.typeSolver = typeSolver;
+    this.reflectionClassAdapter = new ReflectionClassAdapter(clazz, typeSolver, this);
+  }
+
+  ///
+  /// Public methods
+  ///
+
+  @Override
+  public AccessLevel accessLevel() {
+    return ReflectionFactory.modifiersToAccessLevel(this.clazz.getModifiers());
+  }
+  
+  @Override
+  public Optional<ReferenceTypeDeclaration> containerType() {
+      return reflectionClassAdapter.containerType();
+  }
+
+  @Override
+  public String getPackageName() {
+    if (clazz.getPackage() != null) {
+      return clazz.getPackage().getName();
+    }
+    return null;
+  }
+
+  @Override
+  public String getClassName() {
+    String canonicalName = clazz.getCanonicalName();
+    if (canonicalName != null && getPackageName() != null) {
+      return canonicalName.substring(getPackageName().length() + 1, canonicalName.length());
+    }
+    return null;
+  }
+
+  @Override
+  public String getQualifiedName() {
+    return clazz.getCanonicalName();
+  }
+
+  @Override
+  public List<ReferenceType> getAncestors() {
+    return reflectionClassAdapter.getAncestors();
+  }
+
+  @Override
+  public FieldDeclaration getField(String name) {
+    return reflectionClassAdapter.getField(name);
+  }
+
+  @Override
+  public boolean hasField(String name) {
+    return reflectionClassAdapter.hasField(name);
+  }
+
+  @Override
+  public List<FieldDeclaration> getAllFields() {
+    return reflectionClassAdapter.getAllFields();
+  }
+
+  @Override
+  public Set<MethodDeclaration> getDeclaredMethods() {
+    return reflectionClassAdapter.getDeclaredMethods();
+  }
+
+  @Override
+  public boolean isAssignableBy(Type type) {
+    return reflectionClassAdapter.isAssignableBy(type);
+  }
+
+  @Override
+  public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+    return isAssignableBy(new ReferenceTypeImpl(other, typeSolver));
+  }
+
+  @Override
+  public boolean hasDirectlyAnnotation(String qualifiedName) {
+    return reflectionClassAdapter.hasDirectlyAnnotation(qualifiedName);
+  }
+
+  @Override
+  public String getName() {
+    return clazz.getSimpleName();
+  }
+
+  @Override
+  public List<TypeParameterDeclaration> getTypeParameters() {
+    return reflectionClassAdapter.getTypeParameters();
+  }
+
+  public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes, boolean staticOnly) {
+    return ReflectionMethodResolutionLogic.solveMethod(name, parameterTypes, staticOnly,
+            typeSolver,this, clazz);
+  }
+
+  public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> parameterTypes, TypeSolver typeSolver, Context invokationContext, List<Type> typeParameterValues) {
+    Optional<MethodUsage> res = ReflectionMethodResolutionLogic.solveMethodAsUsage(name, parameterTypes, typeSolver, invokationContext,
+            typeParameterValues, this, clazz);
+    if (res.isPresent()) {
+        // We have to replace method type typeParametersValues here
+        InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE);
+        MethodUsage methodUsage = res.get();
+        int i = 0;
+        List<Type> parameters = new LinkedList<>();
+        for (Type actualType : parameterTypes) {
+            Type formalType = methodUsage.getParamType(i);
+            // We need to replace the class type typeParametersValues (while we derive the method ones)
+
+            parameters.add(inferenceContext.addPair(formalType, actualType));
+            i++;
+        }
+        try {
+            Type returnType = inferenceContext.addSingle(methodUsage.returnType());
+            for (int j=0;j<parameters.size();j++) {
+                methodUsage = methodUsage.replaceParamType(j, inferenceContext.resolve(parameters.get(j)));
+            }
+            methodUsage = methodUsage.replaceReturnType(inferenceContext.resolve(returnType));
+            return Optional.of(methodUsage);
+        } catch (ConfilictingGenericTypesException e) {
+            return Optional.empty();
+        }
+    } else {
+        return res;
+    }
+}
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java
new file mode 100644
index 0000000..9683474
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFactory.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.AccessLevel;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionFactory {
+
+    public static ReferenceTypeDeclaration typeDeclarationFor(Class<?> clazz, TypeSolver typeSolver) {
+        if (clazz.isArray()) {
+            throw new IllegalArgumentException("No type declaration available for an Array");
+        } else if (clazz.isPrimitive()) {
+            throw new IllegalArgumentException();
+        } else if (clazz.isInterface()) {
+            return new ReflectionInterfaceDeclaration(clazz, typeSolver);
+        } else if (clazz.isEnum()) {
+            return new ReflectionEnumDeclaration(clazz, typeSolver);
+        } else {
+            return new ReflectionClassDeclaration(clazz, typeSolver);
+        }
+    }
+
+    public static Type typeUsageFor(java.lang.reflect.Type type, TypeSolver typeSolver) {
+        if (type instanceof java.lang.reflect.TypeVariable) {
+            java.lang.reflect.TypeVariable<?> tv = (java.lang.reflect.TypeVariable<?>) type;
+            boolean declaredOnClass = tv.getGenericDeclaration() instanceof java.lang.reflect.Type;
+            TypeParameterDeclaration typeParameter = new ReflectionTypeParameter(tv, declaredOnClass, typeSolver);
+            return new com.github.javaparser.symbolsolver.model.typesystem.TypeVariable(typeParameter);
+        } else if (type instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType) type;
+            ReferenceType rawType = typeUsageFor(pt.getRawType(), typeSolver).asReferenceType();
+            List<java.lang.reflect.Type> actualTypes = new ArrayList<>();
+            actualTypes.addAll(Arrays.asList(pt.getActualTypeArguments()));
+            // we consume the actual types
+            rawType = rawType.transformTypeParameters(tp -> typeUsageFor(actualTypes.remove(0), typeSolver)).asReferenceType();
+            return rawType;
+        } else if (type instanceof Class) {
+            Class<?> c = (Class<?>) type;
+            if (c.isPrimitive()) {
+                if (c.getName().equals(Void.TYPE.getName())) {
+                    return VoidType.INSTANCE;
+                } else {
+                    return PrimitiveType.byName(c.getName());
+                }
+            } else if (c.isArray()) {
+                return new ArrayType(typeUsageFor(c.getComponentType(), typeSolver));
+            } else {
+                return new ReferenceTypeImpl(typeDeclarationFor(c, typeSolver), typeSolver);
+            }
+        } else if (type instanceof GenericArrayType) {
+            GenericArrayType genericArrayType = (GenericArrayType) type;
+            return new ArrayType(typeUsageFor(genericArrayType.getGenericComponentType(), typeSolver));
+        } else if (type instanceof WildcardType) {
+            WildcardType wildcardType = (WildcardType) type;
+            if (wildcardType.getLowerBounds().length > 0 && wildcardType.getUpperBounds().length > 0) {
+                if (wildcardType.getUpperBounds().length == 1 && wildcardType.getUpperBounds()[0].getTypeName().equals("java.lang.Object")) {
+                    // ok, it does not matter
+                }
+            }
+            if (wildcardType.getLowerBounds().length > 0) {
+                if (wildcardType.getLowerBounds().length > 1) {
+                    throw new UnsupportedOperationException();
+                }
+                return Wildcard.superBound(typeUsageFor(wildcardType.getLowerBounds()[0], typeSolver));
+            }
+            if (wildcardType.getUpperBounds().length > 0) {
+                if (wildcardType.getUpperBounds().length > 1) {
+                    throw new UnsupportedOperationException();
+                }
+                return Wildcard.extendsBound(typeUsageFor(wildcardType.getUpperBounds()[0], typeSolver));
+            }
+            return Wildcard.UNBOUNDED;
+        } else {
+            throw new UnsupportedOperationException(type.getClass().getCanonicalName() + " " + type);
+        }
+    }
+
+    static AccessLevel modifiersToAccessLevel(final int modifiers) {
+        if (Modifier.isPublic(modifiers)) {
+            return AccessLevel.PUBLIC;
+        } else if (Modifier.isProtected(modifiers)) {
+            return AccessLevel.PROTECTED;
+        } else if (Modifier.isPrivate(modifiers)) {
+            return AccessLevel.PRIVATE;
+        } else {
+            return AccessLevel.PACKAGE_PROTECTED;
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFieldDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFieldDeclaration.java
new file mode 100644
index 0000000..78ae54b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionFieldDeclaration.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.AccessLevel;
+import com.github.javaparser.symbolsolver.model.declarations.FieldDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionFieldDeclaration implements FieldDeclaration {
+
+    private Field field;
+    private TypeSolver typeSolver;
+    private Type type;
+
+    public ReflectionFieldDeclaration(Field field, TypeSolver typeSolver) {
+        this.field = field;
+        this.typeSolver = typeSolver;
+        this.type = calcType();
+    }
+
+    private ReflectionFieldDeclaration(Field field, TypeSolver typeSolver, Type type) {
+        this.field = field;
+        this.typeSolver = typeSolver;
+        this.type = type;
+    }
+
+    @Override
+    public Type getType() {
+        return type;
+    }
+
+    private Type calcType() {
+        // TODO consider interfaces, enums, primitive types, arrays
+        return ReflectionFactory.typeUsageFor(field.getGenericType(), typeSolver);
+    }
+
+    @Override
+    public String getName() {
+        return field.getName();
+    }
+
+    @Override
+    public boolean isStatic() {
+        return Modifier.isStatic(field.getModifiers());
+    }
+
+    @Override
+    public boolean isField() {
+        return true;
+    }
+
+    @Override
+    public TypeDeclaration declaringType() {
+        return ReflectionFactory.typeDeclarationFor(field.getDeclaringClass(), typeSolver);
+    }
+
+    public FieldDeclaration replaceType(Type fieldType) {
+        return new ReflectionFieldDeclaration(field, typeSolver, fieldType);
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public boolean isType() {
+        return false;
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return ReflectionFactory.modifiersToAccessLevel(field.getModifiers());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java
new file mode 100644
index 0000000..44e26d4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
+import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
+import com.github.javaparser.symbolsolver.logic.ConfilictingGenericTypesException;
+import com.github.javaparser.symbolsolver.logic.InferenceContext;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.NullType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionInterfaceDeclaration extends AbstractTypeDeclaration implements InterfaceDeclaration {
+
+    ///
+    /// Fields
+    ///
+
+    private Class<?> clazz;
+    private TypeSolver typeSolver;
+    private ReflectionClassAdapter reflectionClassAdapter;
+
+    ///
+    /// Constructor
+    ///
+
+    public ReflectionInterfaceDeclaration(Class<?> clazz, TypeSolver typeSolver) {
+        if (!clazz.isInterface()) {
+            throw new IllegalArgumentException();
+        }
+
+        this.clazz = clazz;
+        this.typeSolver = typeSolver;
+        this.reflectionClassAdapter = new ReflectionClassAdapter(clazz, typeSolver, this);
+    }
+
+    ///
+    /// Public methods
+    ///
+
+    @Override
+    public boolean isAssignableBy(ReferenceTypeDeclaration other) {
+        return isAssignableBy(new ReferenceTypeImpl(other, typeSolver));
+    }
+
+    @Override
+    public String getPackageName() {
+        if (clazz.getPackage() != null) {
+            return clazz.getPackage().getName();
+        }
+        return null;
+    }
+
+    @Override
+    public String getClassName() {
+        String canonicalName = clazz.getCanonicalName();
+        if (canonicalName != null && getPackageName() != null) {
+            return canonicalName.substring(getPackageName().length() + 1, canonicalName.length());
+        }
+        return null;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return clazz.getCanonicalName();
+    }
+
+    @Deprecated
+    public SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes, boolean staticOnly) {
+        return ReflectionMethodResolutionLogic.solveMethod(name, parameterTypes, staticOnly,
+                typeSolver,this, clazz);
+    }
+
+    @Override
+    public String toString() {
+        return "ReflectionInterfaceDeclaration{" +
+                "clazz=" + clazz.getCanonicalName() +
+                '}';
+    }
+
+    public Type getUsage(Node node) {
+        return new ReferenceTypeImpl(this, typeSolver);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof ReflectionInterfaceDeclaration)) return false;
+
+        ReflectionInterfaceDeclaration that = (ReflectionInterfaceDeclaration) o;
+
+        if (!clazz.getCanonicalName().equals(that.clazz.getCanonicalName())) return false;
+
+        if (!getTypeParameters().equals(that.getTypeParameters())) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return clazz.hashCode();
+    }
+
+    public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> parameterTypes, TypeSolver typeSolver, Context invokationContext, List<Type> typeParameterValues) {
+        Optional<MethodUsage> res = ReflectionMethodResolutionLogic.solveMethodAsUsage(name, parameterTypes, typeSolver, invokationContext,
+                typeParameterValues, this, clazz);
+        if (res.isPresent()) {
+            // We have to replace method type typeParametersValues here
+            InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE);
+            MethodUsage methodUsage = res.get();
+            int i = 0;
+            List<Type> parameters = new LinkedList<>();
+            for (Type actualType : parameterTypes) {
+                Type formalType = methodUsage.getParamType(i);
+                // We need to replace the class type typeParametersValues (while we derive the method ones)
+
+                parameters.add(inferenceContext.addPair(formalType, actualType));
+                i++;
+            }
+            try {
+                Type returnType = inferenceContext.addSingle(methodUsage.returnType());
+                for (int j=0;j<parameters.size();j++) {
+                    methodUsage = methodUsage.replaceParamType(j, inferenceContext.resolve(parameters.get(j)));
+                }
+                methodUsage = methodUsage.replaceReturnType(inferenceContext.resolve(returnType));
+                return Optional.of(methodUsage);
+            } catch (ConfilictingGenericTypesException e) {
+                return Optional.empty();
+            }
+        } else {
+            return res;
+        }
+    }
+
+    @Override
+    public boolean canBeAssignedTo(ReferenceTypeDeclaration other) {
+        if (other instanceof LambdaArgumentTypePlaceholder) {
+            return isFunctionalInterface();
+        }
+        if (other.getQualifiedName().equals(getQualifiedName())) {
+            return true;
+        }
+        if (this.clazz.getSuperclass() != null
+                && new ReflectionInterfaceDeclaration(clazz.getSuperclass(), typeSolver).canBeAssignedTo(other)) {
+            return true;
+        }
+        for (Class interfaze : clazz.getInterfaces()) {
+            if (new ReflectionInterfaceDeclaration(interfaze, typeSolver).canBeAssignedTo(other)) {
+                return true;
+            }
+        }
+
+        if (other.getQualifiedName().equals(Object.class.getCanonicalName())) {
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type type) {
+        if (type instanceof NullType) {
+            return true;
+        }
+        if (type instanceof LambdaArgumentTypePlaceholder) {
+            return isFunctionalInterface();
+        }
+        if (type.isArray()) {
+            return false;
+        }
+        if (type.isPrimitive()) {
+            return false;
+        }
+        if (type.describe().equals(getQualifiedName())) {
+            return true;
+        }
+        if (type instanceof ReferenceTypeImpl) {
+            ReferenceTypeImpl otherTypeDeclaration = (ReferenceTypeImpl) type;
+            return otherTypeDeclaration.getTypeDeclaration().canBeAssignedTo(this);
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isTypeParameter() {
+        return false;
+    }
+
+    @Override
+    public FieldDeclaration getField(String name) {
+        return reflectionClassAdapter.getField(name);
+    }
+
+    @Override
+    public List<FieldDeclaration> getAllFields() {
+        return reflectionClassAdapter.getAllFields();
+    }
+
+    @Deprecated
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
+        for (Field field : clazz.getFields()) {
+            if (field.getName().equals(name)) {
+                return SymbolReference.solved(new ReflectionFieldDeclaration(field, typeSolver));
+            }
+        }
+        return SymbolReference.unsolved(ValueDeclaration.class);
+    }
+
+    @Override
+    public List<ReferenceType> getAncestors() {
+        return reflectionClassAdapter.getAncestors();
+    }
+
+    @Override
+    public Set<MethodDeclaration> getDeclaredMethods() {
+        return reflectionClassAdapter.getDeclaredMethods();
+    }
+
+    @Override
+    public boolean hasField(String name) {
+        return reflectionClassAdapter.hasField(name);
+    }
+
+    @Override
+    public String getName() {
+        return clazz.getSimpleName();
+    }
+
+    @Override
+    public boolean isInterface() {
+        return true;
+    }
+
+    @Override
+    public List<ReferenceType> getInterfacesExtended() {
+        List<ReferenceType> res = new ArrayList<>();
+        for (Class i : clazz.getInterfaces()) {
+            res.add(new ReferenceTypeImpl(new ReflectionInterfaceDeclaration(i, typeSolver), typeSolver));
+        }
+        return res;
+    }
+    
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        return reflectionClassAdapter.containerType();
+    }
+
+    @Override
+    public Set<ReferenceTypeDeclaration> internalTypes() {
+        return Arrays.stream(this.clazz.getDeclaredClasses())
+                .map(ic -> ReflectionFactory.typeDeclarationFor(ic, typeSolver))
+                .collect(Collectors.toSet());
+    }
+
+    @Override
+    public InterfaceDeclaration asInterface() {
+        return this;
+    }
+
+    @Override
+    public boolean hasDirectlyAnnotation(String canonicalName) {
+        return reflectionClassAdapter.hasDirectlyAnnotation(canonicalName);
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return reflectionClassAdapter.getTypeParameters();
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return ReflectionFactory.modifiersToAccessLevel(this.clazz.getModifiers());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java
new file mode 100644
index 0000000..e32914f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodDeclaration.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.declarations.common.MethodDeclarationCommonLogic;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionMethodDeclaration implements MethodDeclaration {
+
+    private Method method;
+    private TypeSolver typeSolver;
+
+    public ReflectionMethodDeclaration(Method method, TypeSolver typeSolver) {
+        this.method = method;
+        if (method.isSynthetic() || method.isBridge()) {
+            throw new IllegalArgumentException();
+        }
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public String getName() {
+        return method.getName();
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "ReflectionMethodDeclaration{" +
+                "method=" + method +
+                '}';
+    }
+
+    @Override
+    public boolean isType() {
+        return false;
+    }
+
+    @Override
+    public ReferenceTypeDeclaration declaringType() {
+        if (method.getDeclaringClass().isInterface()) {
+            return new ReflectionInterfaceDeclaration(method.getDeclaringClass(), typeSolver);
+        }
+        if (method.getDeclaringClass().isEnum()) {
+            return new ReflectionEnumDeclaration(method.getDeclaringClass(), typeSolver);
+        } else {
+            return new ReflectionClassDeclaration(method.getDeclaringClass(), typeSolver);
+        }
+    }
+
+    @Override
+    public Type getReturnType() {
+        return ReflectionFactory.typeUsageFor(method.getGenericReturnType(), typeSolver);
+    }
+
+    @Override
+    public int getNumberOfParams() {
+        return method.getParameterTypes().length;
+    }
+
+    @Override
+    public ParameterDeclaration getParam(int i) {
+        boolean variadic = false;
+        if (method.isVarArgs()) {
+            variadic = i == (method.getParameterCount() - 1);
+        }
+        return new ReflectionParameterDeclaration(method.getParameterTypes()[i], method.getGenericParameterTypes()[i], typeSolver, variadic);
+    }
+
+    @Override
+    public List<TypeParameterDeclaration> getTypeParameters() {
+        return Arrays.stream(method.getTypeParameters()).map((refTp) -> new ReflectionTypeParameter(refTp, false, typeSolver)).collect(Collectors.toList());
+    }
+
+    public MethodUsage resolveTypeVariables(Context context, List<Type> parameterTypes) {
+        return new MethodDeclarationCommonLogic(this, typeSolver).resolveTypeVariables(context, parameterTypes);
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return Modifier.isAbstract(method.getModifiers());
+    }
+
+    @Override
+    public boolean isDefaultMethod() {
+        return method.isDefault();
+    }
+
+    @Override
+    public boolean isStatic() {
+        return Modifier.isStatic(method.getModifiers());
+    }
+
+    @Override
+    public AccessLevel accessLevel() {
+        return ReflectionFactory.modifiersToAccessLevel(this.method.getModifiers());
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic.java
new file mode 100644
index 0000000..3838bfd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionMethodResolutionLogic.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
+import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+class ReflectionMethodResolutionLogic {
+
+    static SymbolReference<MethodDeclaration> solveMethod(String name, List<Type> parameterTypes, boolean staticOnly,
+                                                          TypeSolver typeSolver, ReferenceTypeDeclaration scopeType,
+                                                          Class clazz){
+        List<MethodDeclaration> methods = new ArrayList<>();
+        Predicate<Method> staticOnlyCheck = m -> !staticOnly || (staticOnly && Modifier.isStatic(m.getModifiers()));
+        for (Method method : clazz.getMethods()) {
+            if (method.isBridge() || method.isSynthetic() || !method.getName().equals(name)|| !staticOnlyCheck.test(method)) continue;
+            MethodDeclaration methodDeclaration = new ReflectionMethodDeclaration(method, typeSolver);
+            methods.add(methodDeclaration);
+        }
+
+        for (ReferenceType ancestor : scopeType.getAncestors()) {
+            SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, parameterTypes, staticOnly, typeSolver);
+            if (ref.isSolved()) {
+                methods.add(ref.getCorrespondingDeclaration());
+            }
+        }
+
+        if (scopeType.getAncestors().isEmpty()){
+            ReferenceTypeImpl objectClass = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
+            SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(objectClass.getTypeDeclaration(), name, parameterTypes, staticOnly, typeSolver);
+            if (ref.isSolved()) {
+                methods.add(ref.getCorrespondingDeclaration());
+            }
+        }
+        return MethodResolutionLogic.findMostApplicable(methods, name, parameterTypes, typeSolver);
+    }
+
+    static Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver,
+                                                    Context invokationContext, List<Type> typeParameterValues,
+                                                    ReferenceTypeDeclaration scopeType, Class clazz) {
+        if (typeParameterValues.size() != scopeType.getTypeParameters().size()) {
+            // if it is zero we are going to ignore them
+            if (!scopeType.getTypeParameters().isEmpty()) {
+                // Parameters not specified, so default to Object
+                typeParameterValues = new ArrayList<>();
+                for (int i = 0; i < scopeType.getTypeParameters().size(); i++) {
+                    typeParameterValues.add(new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver));
+                }
+            }
+        }
+        List<MethodUsage> methods = new ArrayList<>();
+        for (Method method : clazz.getMethods()) {
+            if (method.getName().equals(name) && !method.isBridge() && !method.isSynthetic()) {
+                MethodDeclaration methodDeclaration = new ReflectionMethodDeclaration(method, typeSolver);
+                MethodUsage methodUsage = replaceParams(typeParameterValues, scopeType, methodDeclaration);
+                methods.add(methodUsage);
+            }
+
+        }
+
+        for(ReferenceType ancestor : scopeType.getAncestors()){
+            SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, typeSolver);
+            if (ref.isSolved()){
+                MethodDeclaration correspondingDeclaration = ref.getCorrespondingDeclaration();
+                MethodUsage methodUsage = replaceParams(typeParameterValues, ancestor.getTypeDeclaration(), correspondingDeclaration);
+                methods.add(methodUsage);
+            }
+        }
+
+        if (scopeType.getAncestors().isEmpty()){
+            ReferenceTypeImpl objectClass = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
+            SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(objectClass.getTypeDeclaration(), name, argumentsTypes, typeSolver);
+            if (ref.isSolved()) {
+                MethodUsage usage = replaceParams(typeParameterValues, objectClass.getTypeDeclaration(), ref.getCorrespondingDeclaration());
+                methods.add(usage);
+            }
+        }
+
+        final List<Type> finalTypeParameterValues = typeParameterValues;
+        argumentsTypes = argumentsTypes.stream().map((pt) -> {
+            int i = 0;
+            for (TypeParameterDeclaration tp : scopeType.getTypeParameters()) {
+                pt = pt.replaceTypeVariables(tp, finalTypeParameterValues.get(i));
+                i++;
+            }
+            return pt;
+        }).collect(Collectors.toList());
+        return MethodResolutionLogic.findMostApplicableUsage(methods, name, argumentsTypes, typeSolver);
+    }
+
+    private static MethodUsage replaceParams(List<Type> typeParameterValues, ReferenceTypeDeclaration typeParametrizable, MethodDeclaration methodDeclaration) {
+        MethodUsage methodUsage = new MethodUsage(methodDeclaration);
+        int i = 0;
+
+        // Only replace if we have enough values provided
+        if (typeParameterValues.size() == typeParametrizable.getTypeParameters().size()){
+            for (TypeParameterDeclaration tp : typeParametrizable.getTypeParameters()) {
+                methodUsage = methodUsage.replaceTypeParameter(tp, typeParameterValues.get(i));
+                i++;
+            }
+        }
+
+        for (TypeParameterDeclaration methodTypeParameter : methodDeclaration.getTypeParameters()) {
+            methodUsage = methodUsage.replaceTypeParameter(methodTypeParameter, new TypeVariable(methodTypeParameter));
+        }
+
+        return methodUsage;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration.java
new file mode 100644
index 0000000..e630d18
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionParameterDeclaration.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.ParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionParameterDeclaration implements ParameterDeclaration {
+    private Class<?> type;
+    private java.lang.reflect.Type genericType;
+    private TypeSolver typeSolver;
+    private boolean variadic;
+
+    public ReflectionParameterDeclaration(Class<?> type, java.lang.reflect.Type genericType, TypeSolver typeSolver, boolean variadic) {
+        this.type = type;
+        this.genericType = genericType;
+        this.typeSolver = typeSolver;
+        this.variadic = variadic;
+    }
+
+    @Override
+    public String getName() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        return "ReflectionParameterDeclaration{" +
+                "type=" + type +
+                '}';
+    }
+
+    @Override
+    public boolean isField() {
+        return false;
+    }
+
+    @Override
+    public boolean isParameter() {
+        return true;
+    }
+
+    @Override
+    public boolean isVariadic() {
+        return variadic;
+    }
+
+    @Override
+    public boolean isType() {
+        return false;
+    }
+
+    @Override
+    public Type getType() {
+        return ReflectionFactory.typeUsageFor(genericType, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter.java
new file mode 100644
index 0000000..d553b6e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionTypeParameter.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.reflectionmodel;
+
+import com.github.javaparser.symbolsolver.model.declarations.MethodLikeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParametrizable;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.Method;
+import java.lang.reflect.TypeVariable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionTypeParameter implements TypeParameterDeclaration {
+
+    private TypeVariable typeVariable;
+    private TypeSolver typeSolver;
+    private TypeParametrizable container;
+
+    public ReflectionTypeParameter(TypeVariable typeVariable, boolean declaredOnClass, TypeSolver typeSolver) {
+        GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
+        if (genericDeclaration instanceof Class) {
+            container = ReflectionFactory.typeDeclarationFor((Class) genericDeclaration, typeSolver);
+        } else if (genericDeclaration instanceof Method) {
+            container = new ReflectionMethodDeclaration((Method) genericDeclaration, typeSolver);
+        } else if (genericDeclaration instanceof Constructor) {
+            container = new ReflectionConstructorDeclaration((Constructor) genericDeclaration, typeSolver);
+        }
+        this.typeVariable = typeVariable;
+        this.typeSolver = typeSolver;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof TypeParameterDeclaration)) return false;
+
+        TypeParameterDeclaration that = (TypeParameterDeclaration) o;
+
+        if (!getQualifiedName().equals(that.getQualifiedName())) {
+            return false;
+        }
+        if (declaredOnType() != that.declaredOnType()) {
+            return false;
+        }
+        if (declaredOnMethod() != that.declaredOnMethod()) {
+            return false;
+        }
+        // TODO check bounds
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = typeVariable.hashCode();
+        result = 31 * result + container.hashCode();
+        return result;
+    }
+
+    @Override
+    public String getName() {
+        return typeVariable.getName();
+    }
+
+    @Override
+    public String getContainerQualifiedName() {
+        if (container instanceof ReferenceTypeDeclaration) {
+            return ((ReferenceTypeDeclaration) container).getQualifiedName();
+        } else {
+            return ((MethodLikeDeclaration) container).getQualifiedSignature();
+        }
+    }
+
+    @Override
+    public String getContainerId() {
+        if (container instanceof ReferenceTypeDeclaration) {
+            return ((ReferenceTypeDeclaration) container).getId();
+        } else {
+            return ((MethodLikeDeclaration) container).getQualifiedSignature();
+        }
+    }
+    
+    @Override
+    public TypeParametrizable getContainer() {
+        return this.container;
+    }
+
+    @Override
+    public List<Bound> getBounds(TypeSolver typeSolver) {
+        return Arrays.stream(typeVariable.getBounds()).map((refB) -> Bound.extendsBound(ReflectionFactory.typeUsageFor(refB, typeSolver))).collect(Collectors.toList());
+    }
+
+    @Override
+    public String toString() {
+        return "ReflectionTypeParameter{" +
+                "typeVariable=" + typeVariable +
+                '}';
+    }
+
+    @Override
+    public Optional<ReferenceTypeDeclaration> containerType() {
+        if (container instanceof ReferenceTypeDeclaration) {
+            return Optional.of((ReferenceTypeDeclaration) container);
+        }
+        return Optional.empty();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/ClassComparator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/ClassComparator.java
new file mode 100644
index 0000000..e22c204
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/ClassComparator.java
@@ -0,0 +1,25 @@
+package com.github.javaparser.symbolsolver.reflectionmodel.comparators;
+
+import java.util.Comparator;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ClassComparator implements Comparator<Class<?>> {
+
+    @Override
+    public int compare(Class<?> o1, Class<?> o2) {
+        int subCompare;
+        subCompare = o1.getCanonicalName().compareTo(o2.getCanonicalName());
+        if (subCompare != 0) return subCompare;
+        subCompare = Boolean.compare(o1.isAnnotation(), o2.isAnnotation());
+        if (subCompare != 0) return subCompare;
+        subCompare = Boolean.compare(o1.isArray(), o2.isArray());
+        if (subCompare != 0) return subCompare;
+        subCompare = Boolean.compare(o1.isEnum(), o2.isEnum());
+        if (subCompare != 0) return subCompare;
+        subCompare = Boolean.compare(o1.isInterface(), o2.isInterface());
+        if (subCompare != 0) return subCompare;
+        return 0;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/MethodComparator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/MethodComparator.java
new file mode 100644
index 0000000..9f2fcb1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/MethodComparator.java
@@ -0,0 +1,25 @@
+package com.github.javaparser.symbolsolver.reflectionmodel.comparators;
+
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class MethodComparator implements Comparator<Method> {
+
+    @Override
+    public int compare(Method o1, Method o2) {
+        int compareName = o1.getName().compareTo(o2.getName());
+        if (compareName != 0) return compareName;
+        int compareNParams = o1.getParameterCount() - o2.getParameterCount();
+        if (compareNParams != 0) return compareNParams;
+        for (int i = 0; i < o1.getParameterCount(); i++) {
+            int compareParam = new ParameterComparator().compare(o1.getParameters()[i], o2.getParameters()[i]);
+            if (compareParam != 0) return compareParam;
+        }
+        int compareResult = new ClassComparator().compare(o1.getReturnType(), o2.getReturnType());
+        if (compareResult != 0) return compareResult;
+        return 0;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/ParameterComparator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/ParameterComparator.java
new file mode 100644
index 0000000..42ed6b8
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/comparators/ParameterComparator.java
@@ -0,0 +1,19 @@
+package com.github.javaparser.symbolsolver.reflectionmodel.comparators;
+
+import java.lang.reflect.Parameter;
+import java.util.Comparator;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ParameterComparator implements Comparator<Parameter> {
+
+    @Override
+    public int compare(Parameter o1, Parameter o2) {
+        int compareName = o1.getName().compareTo(o2.getName());
+        if (compareName != 0) return compareName;
+        int compareType = new ClassComparator().compare(o1.getType(), o2.getType());
+        if (compareType != 0) return compareType;
+        return 0;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/package-info.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/package-info.java
new file mode 100644
index 0000000..9e58cbd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/reflectionmodel/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementation of model based on reflection.
+ */
+package com.github.javaparser.symbolsolver.reflectionmodel;
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/ConstructorResolutionLogic.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/ConstructorResolutionLogic.java
new file mode 100644
index 0000000..192eae0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/ConstructorResolutionLogic.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodAmbiguityException;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.ArrayType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author Fred Lefévère-Laoide
+ */
+public class ConstructorResolutionLogic {
+
+    private static List<Type> groupVariadicParamValues(List<Type> argumentsTypes, int startVariadic,
+                                                       Type variadicType) {
+        List<Type> res = new ArrayList<>(argumentsTypes.subList(0, startVariadic));
+        List<Type> variadicValues = argumentsTypes.subList(startVariadic, argumentsTypes.size());
+        if (variadicValues.isEmpty()) {
+            // TODO if there are no variadic values we should default to the bound of the formal type
+            res.add(variadicType);
+        } else {
+            Type componentType = findCommonType(variadicValues);
+            res.add(new ArrayType(componentType));
+        }
+        return res;
+    }
+
+    private static Type findCommonType(List<Type> variadicValues) {
+        if (variadicValues.isEmpty()) {
+            throw new IllegalArgumentException();
+        }
+        // TODO implement this decently
+        return variadicValues.get(0);
+    }
+
+    public static boolean isApplicable(ConstructorDeclaration constructor, List<Type> argumentsTypes,
+                                       TypeSolver typeSolver) {
+        return isApplicable(constructor, argumentsTypes, typeSolver, false);
+    }
+
+    private static boolean isApplicable(ConstructorDeclaration constructor, List<Type> argumentsTypes,
+                                        TypeSolver typeSolver, boolean withWildcardTolerance) {
+        if (constructor.hasVariadicParameter()) {
+            int pos = constructor.getNumberOfParams() - 1;
+            if (constructor.getNumberOfParams() == argumentsTypes.size()) {
+                // check if the last value is directly assignable as an array
+                Type expectedType = constructor.getLastParam().getType();
+                Type actualType = argumentsTypes.get(pos);
+                if (!expectedType.isAssignableBy(actualType)) {
+                    for (TypeParameterDeclaration tp : constructor.getTypeParameters()) {
+                        expectedType = MethodResolutionLogic.replaceTypeParam(expectedType, tp, typeSolver);
+                    }
+                    if (!expectedType.isAssignableBy(actualType)) {
+                        if (actualType.isArray()
+                                && expectedType.isAssignableBy(actualType.asArrayType().getComponentType())) {
+                            argumentsTypes.set(pos, actualType.asArrayType().getComponentType());
+                        } else {
+                            argumentsTypes = groupVariadicParamValues(argumentsTypes, pos,
+                                    constructor.getLastParam().getType());
+                        }
+                    }
+                } // else it is already assignable, nothing to do
+            } else {
+                if (pos > argumentsTypes.size()) {
+                    return false;
+                }
+                argumentsTypes =
+                        groupVariadicParamValues(argumentsTypes, pos, constructor.getLastParam().getType());
+            }
+        }
+
+        if (constructor.getNumberOfParams() != argumentsTypes.size()) {
+            return false;
+        }
+        Map<String, Type> matchedParameters = new HashMap<>();
+        boolean needForWildCardTolerance = false;
+        for (int i = 0; i < constructor.getNumberOfParams(); i++) {
+            Type expectedType = constructor.getParam(i).getType();
+            Type actualType = argumentsTypes.get(i);
+            if ((expectedType.isTypeVariable() && !(expectedType.isWildcard()))
+                    && expectedType.asTypeParameter().declaredOnMethod()) {
+                matchedParameters.put(expectedType.asTypeParameter().getName(), actualType);
+                continue;
+            }
+            boolean isAssignableWithoutSubstitution =
+                    expectedType.isAssignableBy(actualType) || (constructor.getParam(i).isVariadic()
+                            && new ArrayType(expectedType).isAssignableBy(actualType));
+            if (!isAssignableWithoutSubstitution && expectedType.isReferenceType()
+                    && actualType.isReferenceType()) {
+                isAssignableWithoutSubstitution = MethodResolutionLogic.isAssignableMatchTypeParameters(
+                        expectedType.asReferenceType(), actualType.asReferenceType(), matchedParameters);
+            }
+            if (!isAssignableWithoutSubstitution) {
+                List<TypeParameterDeclaration> typeParameters = constructor.getTypeParameters();
+                typeParameters.addAll(constructor.declaringType().getTypeParameters());
+                for (TypeParameterDeclaration tp : typeParameters) {
+                    expectedType = MethodResolutionLogic.replaceTypeParam(expectedType, tp, typeSolver);
+                }
+
+                if (!expectedType.isAssignableBy(actualType)) {
+                    if (actualType.isWildcard() && withWildcardTolerance && !expectedType.isPrimitive()) {
+                        needForWildCardTolerance = true;
+                        continue;
+                    }
+                    if (constructor.hasVariadicParameter() && i == constructor.getNumberOfParams() - 1) {
+                        if (new ArrayType(expectedType).isAssignableBy(actualType)) {
+                            continue;
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+        return !withWildcardTolerance || needForWildCardTolerance;
+    }
+
+    /**
+     * @param methods        we expect the methods to be ordered such that inherited methods are later in the list
+     * @param name
+     * @param argumentsTypes
+     * @param typeSolver
+     * @return
+     */
+    public static SymbolReference<ConstructorDeclaration> findMostApplicable(
+            List<ConstructorDeclaration> constructors, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        SymbolReference<ConstructorDeclaration> res =
+                findMostApplicable(constructors, argumentsTypes, typeSolver, false);
+        if (res.isSolved()) {
+            return res;
+        }
+        return findMostApplicable(constructors, argumentsTypes, typeSolver, true);
+    }
+
+    public static SymbolReference<ConstructorDeclaration> findMostApplicable(List<ConstructorDeclaration> constructors, List<Type> argumentsTypes, TypeSolver typeSolver, boolean wildcardTolerance) {
+        List<ConstructorDeclaration> applicableConstructors = constructors.stream().filter((m) -> isApplicable(m, argumentsTypes, typeSolver, wildcardTolerance)).collect(Collectors.toList());
+        if (applicableConstructors.isEmpty()) {
+            return SymbolReference.unsolved(ConstructorDeclaration.class);
+        }
+        if (applicableConstructors.size() == 1) {
+            return SymbolReference.solved(applicableConstructors.get(0));
+        } else {
+            ConstructorDeclaration winningCandidate = applicableConstructors.get(0);
+            ConstructorDeclaration other = null;
+            boolean possibleAmbiguity = false;
+            for (int i = 1; i < applicableConstructors.size(); i++) {
+                other = applicableConstructors.get(i);
+                if (isMoreSpecific(winningCandidate, other, typeSolver)) {
+                    possibleAmbiguity = false;
+                } else if (isMoreSpecific(other, winningCandidate, typeSolver)) {
+                    possibleAmbiguity = false;
+                    winningCandidate = other;
+                } else {
+                    if (winningCandidate.declaringType().getQualifiedName()
+                            .equals(other.declaringType().getQualifiedName())) {
+                        possibleAmbiguity = true;
+                    } else {
+                        // we expect the methods to be ordered such that inherited methods are later in the list
+                    }
+                }
+            }
+            if (possibleAmbiguity) {
+                // pick the first exact match if it exists
+                if (!MethodResolutionLogic.isExactMatch(winningCandidate, argumentsTypes)) {
+                    if (MethodResolutionLogic.isExactMatch(other, argumentsTypes)) {
+                        winningCandidate = other;
+                    } else {
+                        throw new MethodAmbiguityException("Ambiguous constructor call: cannot find a most applicable constructor: " + winningCandidate + ", " + other);
+                    }
+                }
+            }
+            return SymbolReference.solved(winningCandidate);
+        }
+    }
+
+    private static boolean isMoreSpecific(ConstructorDeclaration constructorA,
+                                          ConstructorDeclaration constructorB, TypeSolver typeSolver) {
+        boolean oneMoreSpecificFound = false;
+        if (constructorA.getNumberOfParams() < constructorB.getNumberOfParams()) {
+            return true;
+        }
+        if (constructorA.getNumberOfParams() > constructorB.getNumberOfParams()) {
+            return false;
+        }
+        for (int i = 0; i < constructorA.getNumberOfParams(); i++) {
+            Type tdA = constructorA.getParam(i).getType();
+            Type tdB = constructorB.getParam(i).getType();
+            // B is more specific
+            if (tdB.isAssignableBy(tdA) && !tdA.isAssignableBy(tdB)) {
+                oneMoreSpecificFound = true;
+            }
+            // A is more specific
+            if (tdA.isAssignableBy(tdB) && !tdB.isAssignableBy(tdA)) {
+                return false;
+            }
+            // if it matches a variadic and a not variadic I pick the not variadic
+            // FIXME
+            if (i == (constructorA.getNumberOfParams() - 1) && tdA.arrayLevel() > tdB.arrayLevel()) {
+                return true;
+            }
+        }
+        return oneMoreSpecificFound;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic.java
new file mode 100644
index 0000000..f78dfa7
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/MethodResolutionLogic.java
@@ -0,0 +1,679 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistEnumDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.*;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionEnumDeclaration;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class MethodResolutionLogic {
+
+    private static List<Type> groupVariadicParamValues(List<Type> argumentsTypes, int startVariadic, Type variadicType) {
+        List<Type> res = new ArrayList<>(argumentsTypes.subList(0, startVariadic));
+        List<Type> variadicValues = argumentsTypes.subList(startVariadic, argumentsTypes.size());
+        if (variadicValues.isEmpty()) {
+            // TODO if there are no variadic values we should default to the bound of the formal type
+            res.add(variadicType);
+        } else {
+            Type componentType = findCommonType(variadicValues);
+            res.add(new ArrayType(componentType));
+        }
+        return res;
+    }
+
+    private static Type findCommonType(List<Type> variadicValues) {
+        if (variadicValues.isEmpty()) {
+            throw new IllegalArgumentException();
+        }
+        // TODO implement this decently
+        return variadicValues.get(0);
+    }
+
+    public static boolean isApplicable(MethodDeclaration method, String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        return isApplicable(method, name, argumentsTypes, typeSolver, false);
+    }
+
+    private static boolean isApplicable(MethodDeclaration method, String name, List<Type> argumentsTypes, TypeSolver typeSolver, boolean withWildcardTolerance) {
+        if (!method.getName().equals(name)) {
+            return false;
+        }
+        if (method.hasVariadicParameter()) {
+            int pos = method.getNumberOfParams() - 1;
+            if (method.getNumberOfParams() == argumentsTypes.size()) {
+                // check if the last value is directly assignable as an array
+                Type expectedType = method.getLastParam().getType();
+                Type actualType = argumentsTypes.get(pos);
+                if (!expectedType.isAssignableBy(actualType)) {
+                    for (TypeParameterDeclaration tp : method.getTypeParameters()) {
+                        expectedType = replaceTypeParam(expectedType, tp, typeSolver);
+                    }
+                    if (!expectedType.isAssignableBy(actualType)) {
+                        if (actualType.isArray() && expectedType.isAssignableBy(actualType.asArrayType().getComponentType())) {
+                            argumentsTypes.set(pos, actualType.asArrayType().getComponentType());
+                        } else {
+                            argumentsTypes = groupVariadicParamValues(argumentsTypes, pos, method.getLastParam().getType());
+                        }
+                    }
+                } // else it is already assignable, nothing to do
+            } else {
+                if (pos > argumentsTypes.size()) {
+                  return false;
+                }
+                argumentsTypes = groupVariadicParamValues(argumentsTypes, pos, method.getLastParam().getType());
+            }
+        }
+
+        if (method.getNumberOfParams() != argumentsTypes.size()) {
+            return false;
+        }
+        Map<String, Type> matchedParameters = new HashMap<>();
+        boolean needForWildCardTolerance = false;
+        for (int i = 0; i < method.getNumberOfParams(); i++) {
+            Type expectedType = method.getParam(i).getType();
+            Type actualType = argumentsTypes.get(i);
+            if ((expectedType.isTypeVariable() && !(expectedType.isWildcard())) && expectedType.asTypeParameter().declaredOnMethod()) {
+                matchedParameters.put(expectedType.asTypeParameter().getName(), actualType);
+                continue;
+            }
+            boolean isAssignableWithoutSubstitution = expectedType.isAssignableBy(actualType) ||
+                    (method.getParam(i).isVariadic() && new ArrayType(expectedType).isAssignableBy(actualType));
+            if (!isAssignableWithoutSubstitution && expectedType.isReferenceType() && actualType.isReferenceType()) {
+                isAssignableWithoutSubstitution = isAssignableMatchTypeParameters(
+                        expectedType.asReferenceType(),
+                        actualType.asReferenceType(),
+                        matchedParameters);
+            }
+            if (!isAssignableWithoutSubstitution) {
+                List<TypeParameterDeclaration> typeParameters = method.getTypeParameters();
+                typeParameters.addAll(method.declaringType().getTypeParameters());
+                for (TypeParameterDeclaration tp : typeParameters) {
+                    expectedType = replaceTypeParam(expectedType, tp, typeSolver);
+                }
+
+                if (!expectedType.isAssignableBy(actualType)) {
+                    if (actualType.isWildcard() && withWildcardTolerance && !expectedType.isPrimitive()) {
+                        needForWildCardTolerance = true;
+                        continue;
+                    }
+                    if (method.hasVariadicParameter() && i == method.getNumberOfParams() - 1) {
+                        if (new ArrayType(expectedType).isAssignableBy(actualType)) {
+                            continue;
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+        return !withWildcardTolerance || needForWildCardTolerance;
+    }
+
+    public static boolean isAssignableMatchTypeParameters(Type expected, Type actual,
+                                                          Map<String, Type> matchedParameters) {
+        if (expected.isReferenceType() && actual.isReferenceType()) {
+            return isAssignableMatchTypeParameters(expected.asReferenceType(), actual.asReferenceType(), matchedParameters);
+        } else if (expected.isTypeVariable()) {
+            matchedParameters.put(expected.asTypeParameter().getName(), actual);
+            return true;
+        } else {
+            throw new UnsupportedOperationException(expected.getClass().getCanonicalName() + " " + actual.getClass().getCanonicalName());
+        }
+    }
+
+    public static boolean isAssignableMatchTypeParameters(ReferenceType expected, ReferenceType actual,
+                                                          Map<String, Type> matchedParameters) {
+        if (actual.getQualifiedName().equals(expected.getQualifiedName())) {
+            return isAssignableMatchTypeParametersMatchingQName(expected, actual, matchedParameters);
+        } else {
+            List<ReferenceType> ancestors = actual.getAllAncestors();
+            for (ReferenceType ancestor : ancestors) {
+                if (isAssignableMatchTypeParametersMatchingQName(expected, ancestor, matchedParameters)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean isAssignableMatchTypeParametersMatchingQName(ReferenceType expected, ReferenceType actual,
+                                                                        Map<String, Type> matchedParameters) {
+
+        if (!expected.getQualifiedName().equals(actual.getQualifiedName())) {
+            return false;
+        }
+        if (expected.typeParametersValues().size() != actual.typeParametersValues().size()) {
+            throw new UnsupportedOperationException();
+            //return true;
+        }
+        for (int i = 0; i < expected.typeParametersValues().size(); i++) {
+            Type expectedParam = expected.typeParametersValues().get(i);
+            Type actualParam = actual.typeParametersValues().get(i);
+
+            // In the case of nested parameterizations eg. List<R> <-> List<Integer>
+            // we should peel off one layer and ensure R <-> Integer
+            if (expectedParam.isReferenceType() && actualParam.isReferenceType()){
+                ReferenceType r1 = expectedParam.asReferenceType();
+                ReferenceType r2 = actualParam.asReferenceType();
+
+                return isAssignableMatchTypeParametersMatchingQName(r1, r2, matchedParameters);
+            }
+
+            if (expectedParam.isTypeVariable()) {
+                String expectedParamName = expectedParam.asTypeParameter().getName();
+                if (!actualParam.isTypeVariable() || !actualParam.asTypeParameter().getName().equals(expectedParamName)) {
+                    if (matchedParameters.containsKey(expectedParamName)) {
+                        Type matchedParameter = matchedParameters.get(expectedParamName);
+                        if (matchedParameter.isAssignableBy(actualParam)) {
+                            return true;
+                        } else if (actualParam.isAssignableBy(matchedParameter)) {
+                            matchedParameters.put(expectedParamName, actualParam);
+                            return true;
+                        }
+                        return false;
+                    } else {
+                        matchedParameters.put(expectedParamName, actualParam);
+                    }
+                }
+            } else if (expectedParam.isReferenceType()) {
+                if (!expectedParam.equals(actualParam)) {
+                    return false;
+                }
+            } else if (expectedParam.isWildcard()) {
+                if (expectedParam.asWildcard().isExtends()) {
+                    return isAssignableMatchTypeParameters(expectedParam.asWildcard().getBoundedType(), actual, matchedParameters);
+                }
+                // TODO verify super bound
+                return true;
+            } else {
+                throw new UnsupportedOperationException(expectedParam.describe());
+            }
+        }
+        return true;
+    }
+
+    public static Type replaceTypeParam(Type type, TypeParameterDeclaration tp, TypeSolver typeSolver) {
+        if (type.isTypeVariable()) {
+            if (type.describe().equals(tp.getName())) {
+                List<TypeParameterDeclaration.Bound> bounds = tp.getBounds(typeSolver);
+                if (bounds.size() > 1) {
+                    throw new UnsupportedOperationException();
+                } else if (bounds.size() == 1) {
+                    return bounds.get(0).getType();
+                } else {
+                    return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
+                }
+            }
+            return type;
+        } else if (type.isPrimitive()) {
+            return type;
+        } else if (type.isArray()) {
+            return new ArrayType(replaceTypeParam(type.asArrayType().getComponentType(), tp, typeSolver));
+        } else if (type.isReferenceType()) {
+            ReferenceType result = type.asReferenceType();
+            result = result.transformTypeParameters(typeParam -> replaceTypeParam(typeParam, tp, typeSolver)).asReferenceType();
+            return result;
+        } else if (type.isWildcard()) {
+            if (type.describe().equals(tp.getName())) {
+                List<TypeParameterDeclaration.Bound> bounds = tp.getBounds(typeSolver);
+                if (bounds.size() > 1) {
+                    throw new UnsupportedOperationException();
+                } else if (bounds.size() == 1) {
+                    return bounds.get(0).getType();
+                } else {
+                    return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver);
+                }
+            }
+            return type;
+        } else {
+            throw new UnsupportedOperationException("Replacing " + type + ", param " + tp + " with " + type.getClass().getCanonicalName());
+        }
+    }
+
+    public static boolean isApplicable(MethodUsage method, String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        if (!method.getName().equals(name)) {
+            return false;
+        }
+        // TODO Consider varargs
+        if (method.getNoParams() != argumentsTypes.size()) {
+            return false;
+        }
+        for (int i = 0; i < method.getNoParams(); i++) {
+            Type expectedType = method.getParamType(i);
+            Type expectedTypeWithoutSubstitutions = expectedType;
+            Type expectedTypeWithInference = method.getParamType(i);
+            Type actualType = argumentsTypes.get(i);
+
+            List<TypeParameterDeclaration> typeParameters = method.getDeclaration().getTypeParameters();
+            typeParameters.addAll(method.declaringType().getTypeParameters());
+
+            if (expectedType.describe().equals(actualType.describe())){
+                return true;
+            }
+
+            Map<TypeParameterDeclaration, Type> derivedValues = new HashMap<>();
+            for (int j = 0; j < method.getParamTypes().size(); j++) {
+                ParameterDeclaration parameter = method.getDeclaration().getParam(i);
+                Type parameterType = parameter.getType();
+                if (parameter.isVariadic()) {
+                    parameterType = parameterType.asArrayType().getComponentType();
+                }
+                inferTypes(argumentsTypes.get(j), parameterType, derivedValues);
+            }
+
+            for (Map.Entry<TypeParameterDeclaration, Type> entry : derivedValues.entrySet()){
+                TypeParameterDeclaration tp = entry.getKey();
+                expectedTypeWithInference = expectedTypeWithInference.replaceTypeVariables(tp, entry.getValue());
+            }
+
+            for (TypeParameterDeclaration tp : typeParameters) {
+                if (tp.getBounds(typeSolver).isEmpty()) {
+                    //expectedType = expectedType.replaceTypeVariables(tp.getName(), new ReferenceTypeUsageImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver));
+                    expectedType = expectedType.replaceTypeVariables(tp, Wildcard.extendsBound(new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver)));
+                } else if (tp.getBounds(typeSolver).size() == 1) {
+                    TypeParameterDeclaration.Bound bound = tp.getBounds(typeSolver).get(0);
+                    if (bound.isExtends()) {
+                        //expectedType = expectedType.replaceTypeVariables(tp.getName(), bound.getType());
+                        expectedType = expectedType.replaceTypeVariables(tp, Wildcard.extendsBound(bound.getType()));
+                    } else {
+                        //expectedType = expectedType.replaceTypeVariables(tp.getName(), new ReferenceTypeUsageImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver));
+                        expectedType = expectedType.replaceTypeVariables(tp, Wildcard.superBound(bound.getType()));
+                    }
+                } else {
+                    throw new UnsupportedOperationException();
+                }
+            }
+            Type expectedType2 = expectedTypeWithoutSubstitutions;
+            for (TypeParameterDeclaration tp : typeParameters) {
+                if (tp.getBounds(typeSolver).isEmpty()) {
+                    expectedType2 = expectedType2.replaceTypeVariables(tp, new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver));
+                } else if (tp.getBounds(typeSolver).size() == 1) {
+                    TypeParameterDeclaration.Bound bound = tp.getBounds(typeSolver).get(0);
+                    if (bound.isExtends()) {
+                        expectedType2 = expectedType2.replaceTypeVariables(tp, bound.getType());
+                    } else {
+                        expectedType2 = expectedType2.replaceTypeVariables(tp, new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver));
+                    }
+                } else {
+                    throw new UnsupportedOperationException();
+                }
+            }
+            if (!expectedType.isAssignableBy(actualType)
+                    && !expectedType2.isAssignableBy(actualType)
+                    && !expectedTypeWithInference.isAssignableBy(actualType)
+                    && !expectedTypeWithoutSubstitutions.isAssignableBy(actualType)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static List<MethodDeclaration> getMethodsWithoutDuplicates(List<MethodDeclaration> methods) {
+        Set<MethodDeclaration> s = new TreeSet<MethodDeclaration>(new Comparator<MethodDeclaration>() {
+            @Override
+            public int compare(MethodDeclaration m1, MethodDeclaration m2) {
+                if (m1 instanceof JavaParserMethodDeclaration && m2 instanceof JavaParserMethodDeclaration &&
+                        ((JavaParserMethodDeclaration) m1).getWrappedNode().equals(((JavaParserMethodDeclaration) m2).getWrappedNode())) {
+                    return 0;
+                }
+                return 1;
+            }
+        });
+        s.addAll(methods);
+        List<MethodDeclaration> res = new ArrayList<>();
+        Set<String> usedSignatures = new HashSet<>();
+        for (MethodDeclaration md : methods) {
+            String signature = md.getQualifiedSignature();
+            if (!usedSignatures.contains(signature)) {
+                usedSignatures.add(signature);
+                res.add(md);
+            }
+        }
+        return res;
+    }
+
+    /**
+     * @param methods        we expect the methods to be ordered such that inherited methods are later in the list
+     * @param name
+     * @param argumentsTypes
+     * @param typeSolver
+     * @return
+     */
+    public static SymbolReference<MethodDeclaration> findMostApplicable(List<MethodDeclaration> methods, String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        SymbolReference<MethodDeclaration> res = findMostApplicable(methods, name, argumentsTypes, typeSolver, false);
+        if (res.isSolved()) {
+            return res;
+        }
+        return findMostApplicable(methods, name, argumentsTypes, typeSolver, true);
+    }
+
+    public static SymbolReference<MethodDeclaration> findMostApplicable(List<MethodDeclaration> methods, String name, List<Type> argumentsTypes, TypeSolver typeSolver, boolean wildcardTolerance) {
+        List<MethodDeclaration> applicableMethods = getMethodsWithoutDuplicates(methods).stream().filter((m) -> isApplicable(m, name, argumentsTypes, typeSolver, wildcardTolerance)).collect(Collectors.toList());
+        if (applicableMethods.isEmpty()) {
+            return SymbolReference.unsolved(MethodDeclaration.class);
+        }
+
+        if (applicableMethods.size() > 1) {
+          List<Integer> nullParamIndexes = new ArrayList<>();
+          for (int i = 0; i < argumentsTypes.size(); i++) {
+            if (argumentsTypes.get(i).isNull()) {
+              nullParamIndexes.add(i);
+            }
+          }
+          if (!nullParamIndexes.isEmpty()) {
+            // remove method with array param if a non array exists and arg is null
+            Set<MethodDeclaration> removeCandidates = new HashSet<>();
+            for (Integer nullParamIndex: nullParamIndexes) {
+              for (MethodDeclaration methDecl: applicableMethods) {
+                if (methDecl.getParam(nullParamIndex.intValue()).getType().isArray()) {
+                  removeCandidates.add(methDecl);
+                }
+              }
+            }
+            if (!removeCandidates.isEmpty() && removeCandidates.size() < applicableMethods.size()) {
+              applicableMethods.removeAll(removeCandidates);
+            }
+          }
+        }
+        if (applicableMethods.size() == 1) {
+            return SymbolReference.solved(applicableMethods.get(0));
+        } else {
+            MethodDeclaration winningCandidate = applicableMethods.get(0);
+            MethodDeclaration other = null;
+            boolean possibleAmbiguity = false;
+            for (int i = 1; i < applicableMethods.size(); i++) {
+                other = applicableMethods.get(i);
+                if (isMoreSpecific(winningCandidate, other, argumentsTypes, typeSolver)) {
+                    possibleAmbiguity = false;
+                } else if (isMoreSpecific(other, winningCandidate, argumentsTypes, typeSolver)) {
+                    possibleAmbiguity = false;
+                    winningCandidate = other;
+                } else {
+                    if (winningCandidate.declaringType().getQualifiedName().equals(other.declaringType().getQualifiedName())) {
+                        possibleAmbiguity = true;
+                    } else {
+                        // we expect the methods to be ordered such that inherited methods are later in the list
+                    }
+                }
+            }
+            if (possibleAmbiguity) {
+              // pick the first exact match if it exists
+              if (!isExactMatch(winningCandidate, argumentsTypes)) {
+                if (isExactMatch(other, argumentsTypes)) {
+                  winningCandidate = other;
+                } else {
+                  throw new MethodAmbiguityException("Ambiguous method call: cannot find a most applicable method: " + winningCandidate + ", " + other);
+                }
+              }
+            }
+            return SymbolReference.solved(winningCandidate);
+        }
+    }
+
+    protected static boolean isExactMatch(MethodLikeDeclaration method, List<Type> argumentsTypes) {
+      for (int i = 0; i < method.getNumberOfParams(); i++) {
+        if (!method.getParam(i).getType().equals(argumentsTypes.get(i))) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    private static boolean isMoreSpecific(MethodDeclaration methodA, MethodDeclaration methodB, List<Type> argumentTypes, TypeSolver typeSolver) {
+        boolean oneMoreSpecificFound = false;
+        if (methodA.getNumberOfParams() < methodB.getNumberOfParams()) {
+            return true;
+        }
+        if (methodA.getNumberOfParams() > methodB.getNumberOfParams()) {
+            return false;
+        }
+        for (int i = 0; i < methodA.getNumberOfParams(); i++) {
+            Type tdA = methodA.getParam(i).getType();
+            Type tdB = methodB.getParam(i).getType();
+            // B is more specific
+            if (tdB.isAssignableBy(tdA) && !tdA.isAssignableBy(tdB)) {
+                oneMoreSpecificFound = true;
+            }
+            // A is more specific
+            if (tdA.isAssignableBy(tdB) && !tdB.isAssignableBy(tdA)) {
+                return false;
+            }
+        }
+
+        if (!oneMoreSpecificFound) {
+            int lastIndex = argumentTypes.size() - 1;
+
+            if (methodA.hasVariadicParameter() && !methodB.hasVariadicParameter()) {
+                // if the last argument is an array then m1 is more specific
+                if (argumentTypes.get(lastIndex).isArray()) {
+                    return true;
+                }
+
+                if (!argumentTypes.get(lastIndex).isArray()) {
+                    return false;
+                }
+            }
+            if (!methodA.hasVariadicParameter() && methodB.hasVariadicParameter()) {
+                // if the last argument is an array and m1 is not variadic then
+                // it is not more specific
+                if (argumentTypes.get(lastIndex).isArray()) {
+                    return false;
+                }
+
+                if (!argumentTypes.get(lastIndex).isArray()) {
+                    return true;
+                }
+            }
+        }
+
+        return oneMoreSpecificFound;
+    }
+
+    private static boolean isMoreSpecific(MethodUsage methodA, MethodUsage methodB, TypeSolver typeSolver) {
+        boolean oneMoreSpecificFound = false;
+        for (int i = 0; i < methodA.getNoParams(); i++) {
+            Type tdA = methodA.getParamType(i);
+            Type tdB = methodB.getParamType(i);
+
+            boolean aIsAssignableByB = tdA.isAssignableBy(tdB);
+            boolean bIsAssignableByA = tdB.isAssignableBy(tdA);
+
+            // B is more specific
+            if (bIsAssignableByA && !aIsAssignableByB) {
+                oneMoreSpecificFound = true;
+            }
+            // A is more specific
+            if (aIsAssignableByB && !bIsAssignableByA) {
+                return false;
+            }
+        }
+        return oneMoreSpecificFound;
+    }
+
+    public static Optional<MethodUsage> findMostApplicableUsage(List<MethodUsage> methods, String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        List<MethodUsage> applicableMethods = methods.stream().filter((m) -> isApplicable(m, name, argumentsTypes, typeSolver)).collect(Collectors.toList());
+
+        if (applicableMethods.isEmpty()) {
+            return Optional.empty();
+        }
+        if (applicableMethods.size() == 1) {
+            return Optional.of(applicableMethods.get(0));
+        } else {
+            MethodUsage winningCandidate = applicableMethods.get(0);
+            for (int i = 1; i < applicableMethods.size(); i++) {
+                MethodUsage other = applicableMethods.get(i);
+                if (isMoreSpecific(winningCandidate, other, typeSolver)) {
+                    // nothing to do
+                } else if (isMoreSpecific(other, winningCandidate, typeSolver)) {
+                    winningCandidate = other;
+                } else {
+                    if (winningCandidate.declaringType().getQualifiedName().equals(other.declaringType().getQualifiedName())) {
+                        if (!areOverride(winningCandidate, other)) {
+                            throw new MethodAmbiguityException("Ambiguous method call: cannot find a most applicable method: " + winningCandidate + ", " + other + ". First declared in " + winningCandidate.declaringType().getQualifiedName());
+                        }
+                    } else {
+                        // we expect the methods to be ordered such that inherited methods are later in the list
+                        //throw new UnsupportedOperationException();
+                    }
+                }
+            }
+            return Optional.of(winningCandidate);
+        }
+    }
+
+    private static boolean areOverride(MethodUsage winningCandidate, MethodUsage other) {
+        if (!winningCandidate.getName().equals(other.getName())) {
+            return false;
+        }
+        if (winningCandidate.getNoParams() != other.getNoParams()) {
+            return false;
+        }
+        for (int i = 0; i < winningCandidate.getNoParams(); i++) {
+            if (!winningCandidate.getParamTypes().get(i).equals(other.getParamTypes().get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static SymbolReference<MethodDeclaration> solveMethodInType(TypeDeclaration typeDeclaration, String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
+        return solveMethodInType(typeDeclaration, name, argumentsTypes, false, typeSolver);
+    }
+
+        /**
+         * Replace TypeDeclaration.solveMethod
+         *
+         * @param typeDeclaration
+         * @param name
+         * @param argumentsTypes
+         * @param staticOnly
+         * @return
+         */
+    public static SymbolReference<MethodDeclaration> solveMethodInType(TypeDeclaration typeDeclaration,
+                                                                       String name, List<Type> argumentsTypes, boolean staticOnly,
+                                                                       TypeSolver typeSolver) {
+        if (typeDeclaration instanceof JavaParserClassDeclaration) {
+            Context ctx = ((JavaParserClassDeclaration) typeDeclaration).getContext();
+            return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+        }
+        if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
+            Context ctx = ((JavaParserInterfaceDeclaration) typeDeclaration).getContext();
+            return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+        }
+        if (typeDeclaration instanceof JavaParserEnumDeclaration) {
+            if (name.equals("values") && argumentsTypes.isEmpty()) {
+                return SymbolReference.solved(new JavaParserEnumDeclaration.ValuesMethod((JavaParserEnumDeclaration) typeDeclaration, typeSolver));
+            }
+            Context ctx = ((JavaParserEnumDeclaration) typeDeclaration).getContext();
+            return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver);
+        }
+        if (typeDeclaration instanceof ReflectionClassDeclaration) {
+            return ((ReflectionClassDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
+        }
+        if (typeDeclaration instanceof ReflectionInterfaceDeclaration) {
+          return ((ReflectionInterfaceDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
+        }
+          if (typeDeclaration instanceof ReflectionEnumDeclaration) {
+            return ((ReflectionEnumDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
+        }
+        if (typeDeclaration instanceof JavassistInterfaceDeclaration) {
+            return ((JavassistInterfaceDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
+        }
+        if (typeDeclaration instanceof JavassistClassDeclaration) {
+          return ((JavassistClassDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
+        }
+          if (typeDeclaration instanceof JavassistEnumDeclaration) {
+            return ((JavassistEnumDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly);
+        }
+        throw new UnsupportedOperationException(typeDeclaration.getClass().getCanonicalName());
+    }
+
+    private static void inferTypes(Type source, Type target, Map<TypeParameterDeclaration, Type> mappings) {
+
+
+        if (source.equals(target)) {
+            return;
+        }
+        if (source.isReferenceType() && target.isReferenceType()) {
+            ReferenceType sourceRefType = source.asReferenceType();
+            ReferenceType targetRefType = target.asReferenceType();
+            if (sourceRefType.getQualifiedName().equals(targetRefType.getQualifiedName())) {
+                if (!sourceRefType.isRawType() && !targetRefType.isRawType()) {
+                    for (int i = 0; i < sourceRefType.typeParametersValues().size(); i++) {
+                        inferTypes(sourceRefType.typeParametersValues().get(i), targetRefType.typeParametersValues().get(i), mappings);
+                    }
+                }
+            }
+            return;
+        }
+        if (source.isReferenceType() && target.isWildcard()) {
+            if (target.asWildcard().isBounded()) {
+                inferTypes(source, target.asWildcard().getBoundedType(), mappings);
+                return;
+            }
+            return;
+        }
+        if (source.isWildcard() && target.isWildcard()) {
+            return;
+        }
+        if (source.isReferenceType() && target.isTypeVariable()) {
+            mappings.put(target.asTypeParameter(), source);
+            return;
+        }
+
+        if (source.isWildcard() && target.isReferenceType()){
+            if (source.asWildcard().isBounded()){
+                inferTypes(source.asWildcard().getBoundedType(), target, mappings);
+            }
+            return;
+        }
+
+        if (source.isWildcard() && target.isTypeVariable()) {
+            mappings.put(target.asTypeParameter(), source);
+            return;
+        }
+        if (source.isTypeVariable() && target.isTypeVariable()) {
+            mappings.put(target.asTypeParameter(), source);
+            return;
+        }
+        if (source.isPrimitive() || target.isPrimitive()) {
+            return;
+        }
+        if (source.isNull()) {
+            return;
+        }
+    }
+
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/SymbolDeclarator.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/SymbolDeclarator.java
new file mode 100644
index 0000000..572ecc7
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/SymbolDeclarator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public interface SymbolDeclarator {
+
+    List<ValueDeclaration> getSymbolDeclarations();
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java
new file mode 100644
index 0000000..35ff35b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/SymbolSolver.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.type.ClassOrInterfaceType;
+import com.github.javaparser.symbolsolver.core.resolution.Context;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
+import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.Value;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class SymbolSolver {
+
+    private TypeSolver typeSolver;
+
+    public SymbolSolver(TypeSolver typeSolver) {
+        if (typeSolver == null) throw new IllegalArgumentException();
+
+        this.typeSolver = typeSolver;
+    }
+
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, Context context) {
+        return context.solveSymbol(name, typeSolver);
+    }
+
+    public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, Node node) {
+        return solveSymbol(name, JavaParserFactory.getContext(node, typeSolver));
+    }
+
+    public Optional<Value> solveSymbolAsValue(String name, Context context) {
+        return context.solveSymbolAsValue(name, typeSolver);
+    }
+
+    public Optional<Value> solveSymbolAsValue(String name, Node node) {
+        Context context = JavaParserFactory.getContext(node, typeSolver);
+        return solveSymbolAsValue(name, context);
+    }
+
+    public SymbolReference<? extends TypeDeclaration> solveType(String name, Context context) {
+        return context.solveType(name, typeSolver);
+    }
+
+    public SymbolReference<? extends TypeDeclaration> solveType(String name, Node node) {
+        return solveType(name, JavaParserFactory.getContext(node, typeSolver));
+    }
+
+    public MethodUsage solveMethod(String methodName, List<Type> argumentsTypes, Context context) {
+        SymbolReference<MethodDeclaration> decl = context.solveMethod(methodName, argumentsTypes, false, typeSolver);
+        if (!decl.isSolved()) {
+            throw new UnsolvedSymbolException(context, methodName);
+        }
+        return new MethodUsage(decl.getCorrespondingDeclaration());
+    }
+
+    public MethodUsage solveMethod(String methodName, List<Type> argumentsTypes, Node node) {
+        return solveMethod(methodName, argumentsTypes, JavaParserFactory.getContext(node, typeSolver));
+    }
+
+    public TypeDeclaration solveType(com.github.javaparser.ast.type.Type type) {
+        if (type instanceof ClassOrInterfaceType) {
+
+            // FIXME should call typesolver here!
+
+            String name = ((ClassOrInterfaceType) type).getName().getId();
+            SymbolReference<TypeDeclaration> ref = JavaParserFactory.getContext(type, typeSolver).solveType(name, typeSolver);
+            if (!ref.isSolved()) {
+                throw new UnsolvedSymbolException(JavaParserFactory.getContext(type, typeSolver), name);
+            }
+            return ref.getCorrespondingDeclaration();
+        } else {
+            throw new UnsupportedOperationException(type.getClass().getCanonicalName());
+        }
+    }
+
+    public Type solveTypeUsage(String name, Context context) {
+        Optional<Type> genericType = context.solveGenericType(name, typeSolver);
+        if (genericType.isPresent()) {
+            return genericType.get();
+        }
+        ReferenceTypeDeclaration typeDeclaration = typeSolver.solveType(name);
+        ReferenceTypeImpl typeUsage = new ReferenceTypeImpl(typeDeclaration, typeSolver);
+        return typeUsage;
+    }
+
+    /**
+     * Solve any possible visible symbols including: fields, internal types, type variables, the type itself or its
+     * containers.
+     * <p>
+     * It should contain its own private fields but not inherited private fields.
+     */
+    public SymbolReference<? extends ValueDeclaration> solveSymbolInType(TypeDeclaration typeDeclaration, String name) {
+        if (typeDeclaration instanceof JavaParserClassDeclaration) {
+            Context ctx = ((JavaParserClassDeclaration) typeDeclaration).getContext();
+            return ctx.solveSymbol(name, typeSolver);
+        }
+        if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
+            Context ctx = ((JavaParserInterfaceDeclaration) typeDeclaration).getContext();
+            return ctx.solveSymbol(name, typeSolver);
+        }
+        if (typeDeclaration instanceof JavaParserEnumDeclaration) {
+            Context ctx = ((JavaParserEnumDeclaration) typeDeclaration).getContext();
+            return ctx.solveSymbol(name, typeSolver);
+        }
+        if (typeDeclaration instanceof ReflectionClassDeclaration) {
+            return ((ReflectionClassDeclaration) typeDeclaration).solveSymbol(name, typeSolver);
+        }
+        if (typeDeclaration instanceof ReflectionInterfaceDeclaration) {
+            return ((ReflectionInterfaceDeclaration) typeDeclaration).solveSymbol(name, typeSolver);
+        }
+        if (typeDeclaration instanceof JavassistClassDeclaration) {
+            return ((JavassistClassDeclaration) typeDeclaration).solveSymbol(name, typeSolver);
+        }
+        return SymbolReference.unsolved(ValueDeclaration.class);
+    }
+
+    /**
+     * Try to solve a symbol just in the declaration, it does not delegate to the container.
+     */
+    @Deprecated
+    public SymbolReference<TypeDeclaration> solveTypeInType(TypeDeclaration typeDeclaration, String name) {
+        if (typeDeclaration instanceof JavaParserClassDeclaration) {
+            return ((JavaParserClassDeclaration) typeDeclaration).solveType(name, typeSolver);
+        }
+        if (typeDeclaration instanceof JavaParserInterfaceDeclaration) {
+            return ((JavaParserInterfaceDeclaration) typeDeclaration).solveType(name, typeSolver);
+        }
+        return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java
new file mode 100644
index 0000000..951c2f4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/CombinedTypeSolver.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.symbolsolver.javaparsermodel.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class CombinedTypeSolver implements TypeSolver {
+
+    private TypeSolver parent;
+    private List<TypeSolver> elements = new ArrayList<>();
+
+    public CombinedTypeSolver(TypeSolver... elements) {
+        for (TypeSolver el : elements) {
+            add(el);
+        }
+    }
+
+    @Override
+    public TypeSolver getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(TypeSolver parent) {
+        this.parent = parent;
+    }
+
+    public void add(TypeSolver typeSolver) {
+        this.elements.add(typeSolver);
+        typeSolver.setParent(this);
+    }
+
+    @Override
+    public SymbolReference<ReferenceTypeDeclaration> tryToSolveType(String name) {
+        for (TypeSolver ts : elements) {
+            SymbolReference<ReferenceTypeDeclaration> res = ts.tryToSolveType(name);
+            if (res.isSolved()) {
+                return res;
+            }
+        }
+        return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+    }
+
+    @Override
+    public ReferenceTypeDeclaration solveType(String name) throws UnsolvedSymbolException {
+        SymbolReference<ReferenceTypeDeclaration> res = tryToSolveType(name);
+        if (res.isSolved()) {
+            return res.getCorrespondingDeclaration();
+        } else {
+            throw new UnsolvedSymbolException(name);
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java
new file mode 100644
index 0000000..064b3bb
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/JarTypeSolver.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.symbolsolver.javassistmodel.JavassistFactory;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.NotFoundException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JarTypeSolver implements TypeSolver {
+
+    private static JarTypeSolver instance;
+
+    private TypeSolver parent;
+    private Map<String, ClasspathElement> classpathElements = new HashMap<>();
+    private ClassPool classPool = new ClassPool(false);
+
+    public JarTypeSolver(String pathToJar) throws IOException {
+        addPathToJar(pathToJar);
+    }
+
+    public static JarTypeSolver getJarTypeSolver(String pathToJar) throws IOException {
+        if (instance == null) {
+            instance = new JarTypeSolver(pathToJar);
+        } else {
+            instance.addPathToJar(pathToJar);
+        }
+        return instance;
+    }
+
+    private void addPathToJar(String pathToJar) throws IOException {
+        try {
+            classPool.appendClassPath(pathToJar);
+            classPool.appendSystemPath();
+        } catch (NotFoundException e) {
+            throw new RuntimeException(e);
+        }
+        JarFile jarFile = new JarFile(pathToJar);
+        JarEntry entry = null;
+        Enumeration<JarEntry> e = jarFile.entries();
+        while (e.hasMoreElements()) {
+            entry = e.nextElement();
+            if (entry != null && !entry.isDirectory() && entry.getName().endsWith(".class")) {
+                String name = entryPathToClassName(entry.getName());
+                classpathElements.put(name, new ClasspathElement(jarFile, entry, name));
+            }
+        }
+    }
+
+    @Override
+    public TypeSolver getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(TypeSolver parent) {
+        this.parent = parent;
+    }
+
+    private String entryPathToClassName(String entryPath) {
+        if (!entryPath.endsWith(".class")) {
+            throw new IllegalStateException();
+        }
+        String className = entryPath.substring(0, entryPath.length() - ".class".length());
+        className = className.replace('/', '.');
+        className = className.replace('$', '.');
+        return className;
+    }
+
+    @Override
+    public SymbolReference<ReferenceTypeDeclaration> tryToSolveType(String name) {
+        try {
+            if (classpathElements.containsKey(name)) {
+                return SymbolReference.solved(
+                        JavassistFactory.toTypeDeclaration(classpathElements.get(name).toCtClass(), getRoot()));
+            } else {
+                return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ReferenceTypeDeclaration solveType(String name) throws UnsolvedSymbolException {
+        SymbolReference<ReferenceTypeDeclaration> ref = tryToSolveType(name);
+        if (ref.isSolved()) {
+            return ref.getCorrespondingDeclaration();
+        } else {
+            throw new UnsolvedSymbolException(name);
+        }
+    }
+
+    private class ClasspathElement {
+        private JarFile jarFile;
+        private JarEntry entry;
+        private String path;
+
+        ClasspathElement(JarFile jarFile, JarEntry entry, String path) {
+            this.jarFile = jarFile;
+            this.entry = entry;
+            this.path = path;
+        }
+
+        CtClass toCtClass() throws IOException {
+            try (InputStream is = jarFile.getInputStream(entry)) {
+                return classPool.makeClass(is);
+            }
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java
new file mode 100644
index 0000000..37c2e59
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/JavaParserTypeSolver.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.symbolsolver.javaparser.Navigator;
+import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class JavaParserTypeSolver implements TypeSolver {
+
+    private File srcDir;
+
+    private TypeSolver parent;
+
+    private Map<String, CompilationUnit> parsedFiles = new HashMap<String, CompilationUnit>();
+    private Map<String, List<CompilationUnit>> parsedDirectories = new HashMap<>();
+    private Map<String, ReferenceTypeDeclaration> foundTypes=new HashMap<>();
+
+    public JavaParserTypeSolver(File srcDir) {
+        this.srcDir = srcDir;
+    }
+
+    @Override
+    public String toString() {
+        return "JavaParserTypeSolver{" +
+                "srcDir=" + srcDir +
+                ", parent=" + parent +
+                '}';
+    }
+
+    @Override
+    public TypeSolver getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(TypeSolver parent) {
+        this.parent = parent;
+    }
+
+
+    private CompilationUnit parse(File srcFile) throws FileNotFoundException {
+        if (!parsedFiles.containsKey(srcFile.getAbsolutePath())) {
+            parsedFiles.put(srcFile.getAbsolutePath(), JavaParser.parse(srcFile));
+        }
+        return parsedFiles.get(srcFile.getAbsolutePath());
+    }
+
+    private List<CompilationUnit> parseDirectory(File srcDirectory) throws FileNotFoundException {
+        if (!parsedDirectories.containsKey(srcDirectory.getAbsolutePath())) {
+            List<CompilationUnit> units = new ArrayList<>();
+            File[] files = srcDirectory.listFiles();
+            if (files == null) throw new FileNotFoundException(srcDirectory.getAbsolutePath());
+            for (File file : files) {
+                if (file.getName().toLowerCase().endsWith(".java")) {
+                    units.add(parse(file));
+                }
+            }
+            parsedDirectories.put(srcDirectory.getAbsolutePath(), units);
+        }
+
+        return parsedDirectories.get(srcDirectory.getAbsolutePath());
+    }
+
+    @Override
+    public SymbolReference<ReferenceTypeDeclaration> tryToSolveType(String name) {
+        if (!srcDir.exists() || !srcDir.isDirectory()) {
+            throw new IllegalStateException("SrcDir does not exist or is not a directory: " + srcDir.getAbsolutePath());
+        }
+
+        // TODO support enums
+        // TODO support interfaces
+        if (foundTypes.containsKey(name))
+        	return SymbolReference.solved(foundTypes.get(name));
+
+        SymbolReference<ReferenceTypeDeclaration> result = tryToSolveTypeUncached(name);
+        if (result.isSolved()) {
+            foundTypes.put(name, result.getCorrespondingDeclaration());
+        }
+
+        return result;
+    }
+
+    private SymbolReference<ReferenceTypeDeclaration> tryToSolveTypeUncached(String name) {
+        String[] nameElements = name.split("\\.");
+
+        for (int i = nameElements.length; i > 0; i--) {
+            String filePath = srcDir.getAbsolutePath();
+            for (int j = 0; j < i; j++) {
+                filePath += "/" + nameElements[j];
+            }
+            filePath += ".java";
+
+            String typeName = "";
+            for (int j = i - 1; j < nameElements.length; j++) {
+                if (j != i - 1) {
+                    typeName += ".";
+                }
+                typeName += nameElements[j];
+            }
+
+            File srcFile = new File(filePath);
+            try {
+                CompilationUnit compilationUnit = parse(srcFile);
+                Optional<com.github.javaparser.ast.body.TypeDeclaration<?>> astTypeDeclaration = Navigator.findType(compilationUnit, typeName);
+                if (astTypeDeclaration.isPresent()) {
+                    return SymbolReference.solved(JavaParserFacade.get(this).getTypeDeclaration(astTypeDeclaration.get()));
+                }
+            } catch (FileNotFoundException e) {
+                // Ignore
+            }
+
+            try {
+                List<CompilationUnit> compilationUnits = parseDirectory(srcFile.getParentFile());
+                for (CompilationUnit compilationUnit : compilationUnits) {
+                    Optional<com.github.javaparser.ast.body.TypeDeclaration<?>> astTypeDeclaration = Navigator.findType(compilationUnit, typeName);
+                    if (astTypeDeclaration.isPresent()) {
+                        return SymbolReference.solved(JavaParserFacade.get(this).getTypeDeclaration(astTypeDeclaration.get()));
+                    }
+                }
+            } catch (FileNotFoundException e) {
+                // Ignore
+            }
+        }
+
+        return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver.java
new file mode 100644
index 0000000..c904e1d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/MemoryTypeSolver.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A TypeSolver which only consider the TypeDeclarations provided to it.
+ *
+ * @author Federico Tomassetti
+ */
+public class MemoryTypeSolver implements TypeSolver {
+
+    private TypeSolver parent;
+    private Map<String, ReferenceTypeDeclaration> declarationMap = new HashMap<>();
+
+    @Override
+    public String toString() {
+        return "MemoryTypeSolver{" +
+                "parent=" + parent +
+                ", declarationMap=" + declarationMap +
+                '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof MemoryTypeSolver)) return false;
+
+        MemoryTypeSolver that = (MemoryTypeSolver) o;
+
+        if (parent != null ? !parent.equals(that.parent) : that.parent != null) return false;
+        return !(declarationMap != null ? !declarationMap.equals(that.declarationMap) : that.declarationMap != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = parent != null ? parent.hashCode() : 0;
+        result = 31 * result + (declarationMap != null ? declarationMap.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public TypeSolver getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(TypeSolver parent) {
+        this.parent = parent;
+    }
+
+    public void addDeclaration(String name, ReferenceTypeDeclaration typeDeclaration) {
+        this.declarationMap.put(name, typeDeclaration);
+    }
+
+    @Override
+    public SymbolReference<ReferenceTypeDeclaration> tryToSolveType(String name) {
+        if (declarationMap.containsKey(name)) {
+            return SymbolReference.solved(declarationMap.get(name));
+        } else {
+            return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java
new file mode 100644
index 0000000..d8bd44a
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-core/com/github/javaparser/symbolsolver/resolution/typesolvers/ReflectionTypeSolver.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.resolution.typesolvers;
+
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
+
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ReflectionTypeSolver implements TypeSolver {
+
+    private TypeSolver parent;
+
+    public ReflectionTypeSolver(boolean jreOnly) {
+        this.jreOnly = jreOnly;
+    }
+
+    public ReflectionTypeSolver() {
+        this(true);
+    }
+
+    private boolean jreOnly;
+
+    @Override
+    public TypeSolver getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(TypeSolver parent) {
+        this.parent = parent;
+    }
+
+    @Override
+    public SymbolReference<ReferenceTypeDeclaration> tryToSolveType(String name) {
+        if (!jreOnly || (name.startsWith("java.") || name.startsWith("javax."))) {
+            try {
+                ClassLoader classLoader = ReflectionTypeSolver.class.getClassLoader();
+
+                // Some implementations could return null when the class was loaded through the bootstrap classloader
+                // see https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getClassLoader--
+                if (classLoader == null) {
+                    throw new RuntimeException("The ReflectionTypeSolver has been probably loaded through the bootstrap class loader. This usage is not supported by the JavaSymbolSolver");
+                }
+
+                Class<?> clazz = classLoader.loadClass(name);
+                return SymbolReference.solved(ReflectionFactory.typeDeclarationFor(clazz, getRoot()));
+            } catch (ClassNotFoundException e) {
+                // it could be an inner class
+                int lastDot = name.lastIndexOf('.');
+                if (lastDot == -1) {
+                    return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+                } else {
+                    String parentName = name.substring(0, lastDot);
+                    String childName = name.substring(lastDot + 1);
+                    SymbolReference<ReferenceTypeDeclaration> parent = tryToSolveType(parentName);
+                    if (parent.isSolved()) {
+                        Optional<ReferenceTypeDeclaration> innerClass = parent.getCorrespondingDeclaration().internalTypes()
+                                .stream().filter(it -> it.getName().equals(childName)).findFirst();
+                        if (innerClass.isPresent()) {
+                            return SymbolReference.solved(innerClass.get());
+                        } else {
+                            return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+                        }
+                    } else {
+                        return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+                    }
+                }
+            }
+        } else {
+            return SymbolReference.unsolved(ReferenceTypeDeclaration.class);
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration.java
new file mode 100644
index 0000000..a88e8a8
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/AbstractClassDeclaration.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.symbolsolver.model.declarations.ClassDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A common ancestor for all ClassDeclarations.
+ *
+ * @author Federico Tomassetti
+ */
+public abstract class AbstractClassDeclaration extends AbstractTypeDeclaration implements ClassDeclaration {
+
+    ///
+    /// Public
+    ///
+
+    @Override
+    public boolean hasName() {
+        return getQualifiedName() != null;
+    }
+
+    @Override
+    public final List<ReferenceType> getAllSuperClasses() {
+        List<ReferenceType> superclasses = new ArrayList<>();
+        ReferenceType superClass = getSuperClass();
+        if (superClass != null) {
+            superclasses.add(superClass);
+            superclasses.addAll(superClass.getAllClassesAncestors());
+        }
+
+        if (superclasses.removeIf(s -> s.getQualifiedName().equals(Object.class.getCanonicalName()))) {
+            superclasses.add(object());
+        }
+        return superclasses;
+    }
+
+    @Override
+    public final List<ReferenceType> getAllInterfaces() {
+        List<ReferenceType> interfaces = new ArrayList<>();
+        for (ReferenceType interfaceDeclaration : getInterfaces()) {
+            interfaces.add(interfaceDeclaration);
+            interfaces.addAll(interfaceDeclaration.getAllInterfacesAncestors());
+        }
+        ReferenceType superClass = this.getSuperClass();
+        if (superClass != null) {
+            interfaces.addAll(superClass.getAllInterfacesAncestors());
+        }
+        return interfaces;
+    }
+
+    @Override
+    public final ClassDeclaration asClass() {
+        return this;
+    }
+
+    ///
+    /// Protected
+    ///
+
+    /**
+     * An implementation of the Object class.
+     */
+    protected abstract ReferenceType object();
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java
new file mode 100644
index 0000000..db86ef1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Common ancestor for most types.
+ *
+ * @author Federico Tomassetti
+ */
+public abstract class AbstractTypeDeclaration implements ReferenceTypeDeclaration {
+
+    @Override
+    public final Set<MethodUsage> getAllMethods() {
+        Set<MethodUsage> methods = new HashSet<>();
+
+        Set<String> methodsSignatures = new HashSet<>();
+
+        for (MethodDeclaration methodDeclaration : getDeclaredMethods()) {
+            methods.add(new MethodUsage(methodDeclaration));
+            methodsSignatures.add(methodDeclaration.getSignature());
+        }
+
+        for (ReferenceType ancestor : getAllAncestors()) {
+            for (MethodUsage mu : ancestor.getDeclaredMethods()) {
+                String signature = mu.getDeclaration().getSignature();
+                if (!methodsSignatures.contains(signature)) {
+                    methodsSignatures.add(signature);
+                    methods.add(mu);
+                }
+            }
+        }
+
+        return methods;
+    }
+
+    @Override
+    public final boolean isFunctionalInterface() {
+        return FunctionalInterfaceLogic.getFunctionalMethod(this).isPresent();
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/ConfilictingGenericTypesException.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/ConfilictingGenericTypesException.java
new file mode 100644
index 0000000..573556c
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/ConfilictingGenericTypesException.java
@@ -0,0 +1,13 @@
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class ConfilictingGenericTypesException extends RuntimeException {
+
+    public ConfilictingGenericTypesException(Type formalType, Type actualType) {
+        super(String.format("No matching between %s (formal) and %s (actual)", formalType, actualType));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic.java
new file mode 100644
index 0000000..556b442
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/FunctionalInterfaceLogic.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public final class FunctionalInterfaceLogic {
+
+    private FunctionalInterfaceLogic() {
+        // prevent instantiation
+    }
+
+    /**
+     * Get the functional method defined by the type, if any.
+     */
+    public static Optional<MethodUsage> getFunctionalMethod(Type type) {
+        if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isInterface()) {
+            return getFunctionalMethod(type.asReferenceType().getTypeDeclaration());
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Get the functional method defined by the type, if any.
+     */
+    public static Optional<MethodUsage> getFunctionalMethod(ReferenceTypeDeclaration typeDeclaration) {
+        //We need to find all abstract methods
+        Set<MethodUsage> methods = typeDeclaration.getAllMethods().stream()
+                .filter(m -> m.getDeclaration().isAbstract())
+                // Remove methods inherited by Object:
+                // Consider the case of Comparator which define equals. It would be considered a functional method.
+                .filter(m -> !declaredOnObject(m))
+                .collect(Collectors.toSet());
+
+        if (methods.size() == 1) {
+            return Optional.of(methods.iterator().next());
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    private static String getSignature(Method m) {
+        return String.format("%s(%s)", m.getName(), String.join(", ", Arrays.stream(m.getParameters()).map(p -> toSignature(p)).collect(Collectors.toList())));
+    }
+
+    private static String toSignature(Parameter p) {
+        return p.getType().getCanonicalName();
+    }
+
+    private static List<String> OBJECT_METHODS_SIGNATURES = Arrays.stream(Object.class.getDeclaredMethods())
+            .map(method -> getSignature(method))
+            .collect(Collectors.toList());
+
+    private static boolean declaredOnObject(MethodUsage m) {
+        return OBJECT_METHODS_SIGNATURES.contains(m.getDeclaration().getSignature());
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/InferenceContext.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/InferenceContext.java
new file mode 100644
index 0000000..c1ccc62
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/InferenceContext.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class InferenceContext {
+
+    private int nextInferenceVariableId = 0;
+    private ObjectProvider objectProvider;
+    private List<InferenceVariableType> inferenceVariableTypes = new ArrayList<>();
+
+    public InferenceContext(ObjectProvider objectProvider) {
+        this.objectProvider = objectProvider;
+    }
+
+    private Map<String, InferenceVariableType> inferenceVariableTypeMap = new HashMap<>();
+
+    private InferenceVariableType inferenceVariableTypeForTp(TypeParameterDeclaration tp) {
+        if (!inferenceVariableTypeMap.containsKey(tp.getName())) {
+            InferenceVariableType inferenceVariableType = new InferenceVariableType(nextInferenceVariableId++, objectProvider);
+            inferenceVariableTypes.add(inferenceVariableType);
+            inferenceVariableType.setCorrespondingTp(tp);
+            inferenceVariableTypeMap.put(tp.getName(), inferenceVariableType);
+        }
+        return inferenceVariableTypeMap.get(tp.getName());
+    }
+
+    /**
+     *
+     * @return the actual with the inference variable inserted
+     */
+    public Type addPair(Type target, Type actual) {
+        target = placeInferenceVariables(target);
+        actual = placeInferenceVariables(actual);
+        registerCorrespondance(target, actual);
+        return target;
+    }
+
+    public Type addSingle(Type actual) {
+        return placeInferenceVariables(actual);
+    }
+
+    private void registerCorrespondance(Type formalType, Type actualType) {
+        if (formalType.isReferenceType() && actualType.isReferenceType()) {
+            ReferenceType formalTypeAsReference = formalType.asReferenceType();
+            ReferenceType actualTypeAsReference = actualType.asReferenceType();
+
+            if (!formalTypeAsReference.getQualifiedName().equals(actualTypeAsReference.getQualifiedName())) {
+                List<ReferenceType> ancestors = actualTypeAsReference.getAllAncestors();
+                final String formalParamTypeQName = formalTypeAsReference.getQualifiedName();
+                List<Type> correspondingFormalType = ancestors.stream().filter((a) -> a.getQualifiedName().equals(formalParamTypeQName)).collect(Collectors.toList());
+                if (correspondingFormalType.isEmpty()) {
+                    ancestors = formalTypeAsReference.getAllAncestors();
+                    final String actualParamTypeQname = actualTypeAsReference.getQualifiedName();
+                    List<Type> correspondingActualType = ancestors.stream().filter(a -> a.getQualifiedName().equals(actualParamTypeQname)).collect(Collectors.toList());
+                    if (correspondingActualType.isEmpty()){
+                        throw new ConfilictingGenericTypesException(formalType, actualType);
+                    }
+                    correspondingFormalType = correspondingActualType;
+
+                }
+                actualTypeAsReference = correspondingFormalType.get(0).asReferenceType();
+            }
+
+            if (formalTypeAsReference.getQualifiedName().equals(actualTypeAsReference.getQualifiedName())) {
+                if (!formalTypeAsReference.typeParametersValues().isEmpty()) {
+                    if (actualTypeAsReference.isRawType()) {
+                        // nothing to do
+                    } else {
+                        int i = 0;
+                        for (Type formalTypeParameter : formalTypeAsReference.typeParametersValues()) {
+                            registerCorrespondance(formalTypeParameter, actualTypeAsReference.typeParametersValues().get(i));
+                            i++;
+                        }
+                    }
+                }
+            }
+        } else if (formalType instanceof InferenceVariableType && !actualType.isPrimitive()) {
+            ((InferenceVariableType) formalType).registerEquivalentType(actualType);
+            if (actualType instanceof InferenceVariableType) {
+                ((InferenceVariableType) actualType).registerEquivalentType(formalType);
+            }
+        } else if (actualType.isNull()) {
+            // nothing to do
+        } else if (actualType.equals(formalType)) {
+            // nothing to do
+        } else if (actualType.isArray() && formalType.isArray()) {
+            registerCorrespondance(formalType.asArrayType().getComponentType(), actualType.asArrayType().getComponentType());
+        } else if (formalType.isWildcard()) {
+            // nothing to do
+            if ((actualType instanceof InferenceVariableType) && formalType.asWildcard().isBounded()) {
+                ((InferenceVariableType) actualType).registerEquivalentType(formalType.asWildcard().getBoundedType());
+                if (formalType.asWildcard().getBoundedType() instanceof InferenceVariableType) {
+                    ((InferenceVariableType) formalType.asWildcard().getBoundedType()).registerEquivalentType(actualType);
+                }
+            }
+            if (actualType.isWildcard()) {
+                Wildcard formalWildcard = formalType.asWildcard();
+                Wildcard actualWildcard = actualType.asWildcard();
+                if (formalWildcard.isBounded() && formalWildcard.getBoundedType() instanceof InferenceVariableType) {
+                    if (formalWildcard.isSuper() && actualWildcard.isSuper()) {
+                        ((InferenceVariableType) formalType.asWildcard().getBoundedType()).registerEquivalentType(actualWildcard.getBoundedType());
+                    } else if (formalWildcard.isExtends() && actualWildcard.isExtends()) {
+                        ((InferenceVariableType) formalType.asWildcard().getBoundedType()).registerEquivalentType(actualWildcard.getBoundedType());
+                    }
+                }
+            }
+
+            if (actualType.isReferenceType()){
+                if (formalType.asWildcard().isBounded()){
+                    registerCorrespondance(formalType.asWildcard().getBoundedType(), actualType);
+                }
+            }
+        } else if (actualType instanceof InferenceVariableType){
+            if (formalType instanceof ReferenceType){
+                ((InferenceVariableType) actualType).registerEquivalentType(formalType);
+            } else if (formalType instanceof InferenceVariableType){
+                ((InferenceVariableType) actualType).registerEquivalentType(formalType);
+            }
+        } else if (actualType.isConstraint()){
+            LambdaConstraintType constraintType = actualType.asConstraintType();
+            if (constraintType.getBound() instanceof InferenceVariableType){
+                ((InferenceVariableType) constraintType.getBound()).registerEquivalentType(formalType);
+            }
+        } else if (actualType.isPrimitive()) {
+            if (formalType.isPrimitive()) {
+                // nothing to do
+            } else {
+                registerCorrespondance(formalType, objectProvider.byName(actualType.asPrimitive().getBoxTypeQName()));
+            }
+        } else {
+            throw new UnsupportedOperationException(formalType.describe() + " " + actualType.describe());
+        }
+    }
+
+    private Type placeInferenceVariables(Type type) {
+        if (type.isWildcard()) {
+            if (type.asWildcard().isExtends()) {
+                return Wildcard.extendsBound(placeInferenceVariables(type.asWildcard().getBoundedType()));
+            } else if (type.asWildcard().isSuper()) {
+                return Wildcard.superBound(placeInferenceVariables(type.asWildcard().getBoundedType()));
+            } else {
+                return type;
+            }
+        } else if (type.isTypeVariable()) {
+            return inferenceVariableTypeForTp(type.asTypeParameter());
+        } else if (type.isReferenceType()) {
+            return type.asReferenceType().transformTypeParameters(tp -> placeInferenceVariables(tp));
+        } else if (type.isArray()) {
+            return new ArrayType(placeInferenceVariables(type.asArrayType().getComponentType()));
+        } else if (type.isNull() || type.isPrimitive() || type.isVoid()) {
+            return type;
+        } else if (type.isConstraint()){
+            return LambdaConstraintType.bound(placeInferenceVariables(type.asConstraintType().getBound()));
+        } else if (type instanceof InferenceVariableType) {
+            return type;
+        } else {
+            throw new UnsupportedOperationException(type.describe());
+        }
+    }
+
+    public Type resolve(Type type) {
+        if (type instanceof InferenceVariableType) {
+            InferenceVariableType inferenceVariableType = (InferenceVariableType) type;
+            return inferenceVariableType.equivalentType();
+        } else if (type.isReferenceType()) {
+            return type.asReferenceType().transformTypeParameters(tp -> resolve(tp));
+        } else if (type.isNull() || type.isPrimitive() || type.isVoid()) {
+            return type;
+        } else if (type.isArray()) {
+            return new ArrayType(resolve(type.asArrayType().getComponentType()));
+        } else if (type.isWildcard()) {
+            if (type.asWildcard().isExtends()) {
+                return Wildcard.extendsBound(resolve(type.asWildcard().getBoundedType()));
+            } else if (type.asWildcard().isSuper()) {
+                return Wildcard.superBound(resolve(type.asWildcard().getBoundedType()));
+            } else {
+                return type;
+            }
+        } else {
+            throw new UnsupportedOperationException(type.describe());
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/InferenceVariableType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/InferenceVariableType.java
new file mode 100644
index 0000000..632c2e2
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/InferenceVariableType.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
+import com.github.javaparser.symbolsolver.model.typesystem.Wildcard;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * An element using during type inference.
+ *
+ * @author Federico Tomassetti
+ */
+public class InferenceVariableType implements Type {
+    @Override
+    public String toString() {
+        return "InferenceVariableType{" +
+                "id=" + id +
+                '}';
+    }
+
+    private int id;
+    private TypeParameterDeclaration correspondingTp;
+
+    public void setCorrespondingTp(TypeParameterDeclaration correspondingTp) {
+        this.correspondingTp = correspondingTp;
+    }
+
+    private Set<Type> equivalentTypes = new HashSet<>();
+    private ObjectProvider objectProvider;
+
+    public void registerEquivalentType(Type type) {
+        this.equivalentTypes.add(type);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof InferenceVariableType)) return false;
+
+        InferenceVariableType that = (InferenceVariableType) o;
+
+        return id == that.id;
+
+    }
+
+    @Override
+    public int hashCode() {
+        return id;
+    }
+
+    private Set<Type> superTypes = new HashSet<>();
+
+    public InferenceVariableType(int id, ObjectProvider objectProvider) {
+        this.id = id;
+        this.objectProvider = objectProvider;
+    }
+
+    public static InferenceVariableType fromWildcard(Wildcard wildcard, int id, ObjectProvider objectProvider) {
+        InferenceVariableType inferenceVariableType = new InferenceVariableType(id, objectProvider);
+        if (wildcard.isExtends()) {
+            inferenceVariableType.superTypes.add(wildcard.getBoundedType());
+        }
+        if (wildcard.isSuper()) {
+            // I am not sure about this one...
+            inferenceVariableType.superTypes.add(wildcard.getBoundedType());
+        }
+        return inferenceVariableType;
+    }
+
+    @Override
+    public String describe() {
+        return "InferenceVariable_" + id;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        throw new UnsupportedOperationException();
+    }
+
+    private Set<Type> concreteEquivalentTypesAlsoIndirectly(Set<InferenceVariableType> considered, InferenceVariableType inferenceVariableType) {
+        considered.add(inferenceVariableType);
+        Set<Type> result = new HashSet<>();
+        result.addAll(inferenceVariableType.equivalentTypes.stream().filter(t -> !t.isTypeVariable() && !(t instanceof InferenceVariableType)).collect(Collectors.toSet()));
+        inferenceVariableType.equivalentTypes.stream().filter(t -> t instanceof InferenceVariableType).forEach(t -> {
+            InferenceVariableType ivt = (InferenceVariableType)t;
+            if (!considered.contains(ivt)) {
+                result.addAll(concreteEquivalentTypesAlsoIndirectly(considered, ivt));
+            }
+        });
+        return result;
+    }
+
+    public Type equivalentType() {
+        Set<Type> concreteEquivalent = concreteEquivalentTypesAlsoIndirectly(new HashSet<>(), this);
+        if (concreteEquivalent.isEmpty()) {
+            if (correspondingTp == null) {
+                return objectProvider.object();
+            } else {
+                return new TypeVariable(correspondingTp);
+            }
+        }
+        if (concreteEquivalent.size() == 1) {
+            return concreteEquivalent.iterator().next();
+        }
+        Set<Type> notTypeVariables = equivalentTypes.stream()
+                                                    .filter(t -> !t.isTypeVariable() && !hasInferenceVariables(t))
+                                                    .collect(Collectors.toSet());
+        if (notTypeVariables.size() == 1) {
+            return notTypeVariables.iterator().next();
+        } else if (notTypeVariables.size() == 0 && !superTypes.isEmpty()) {
+            if (superTypes.size() == 1) {
+                return superTypes.iterator().next();
+            } else {
+                throw new IllegalStateException("Super types are: " + superTypes);
+            }
+        } else {
+            throw new IllegalStateException("Equivalent types are: " + equivalentTypes);
+        }
+    }
+
+    private boolean hasInferenceVariables(Type type){
+        if (type instanceof InferenceVariableType){
+            return true;
+        }
+
+        if (type.isReferenceType()){
+            ReferenceType refType = type.asReferenceType();
+            for (Type t : refType.typeParametersValues()){
+                if (hasInferenceVariables(t)){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        if (type.isWildcard()){
+            Wildcard wildcardType = type.asWildcard();
+            return hasInferenceVariables(wildcardType.getBoundedType());
+        }
+
+        return false;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/ObjectProvider.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/ObjectProvider.java
new file mode 100644
index 0000000..e5c970b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-logic/com/github/javaparser/symbolsolver/logic/ObjectProvider.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.logic;
+
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+
+/**
+ * @author Federico Tomassetti
+ */
+public interface ObjectProvider {
+    ReferenceType object();
+    ReferenceType byName(String qname);
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/AccessLevel.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/AccessLevel.java
new file mode 100644
index 0000000..5adafcd
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/AccessLevel.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * @author Federico Tomassetti
+ */
+public enum AccessLevel {
+    PUBLIC,
+    PRIVATE,
+    PROTECTED,
+    PACKAGE_PROTECTED
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/AnnotationDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/AnnotationDeclaration.java
new file mode 100644
index 0000000..3949862
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/AnnotationDeclaration.java
@@ -0,0 +1,7 @@
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * @author Federico Tomassetti
+ */
+public interface AnnotationDeclaration extends ReferenceTypeDeclaration {
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ClassDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ClassDeclaration.java
new file mode 100644
index 0000000..727a378
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ClassDeclaration.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+
+import java.util.List;
+
+/**
+ * Declaration of a Class (not an interface or an enum).
+ *
+ * @author Federico Tomassetti
+ */
+public interface ClassDeclaration extends ReferenceTypeDeclaration, TypeParametrizable, HasAccessLevel {
+
+    /**
+     * This method should always return true.
+     */
+    @Override
+    default boolean isClass() {
+        return true;
+    }
+
+    /**
+     * This is a ReferenceTypeUsage because it could contain type typeParametersValues.
+     * For example: class A extends B<Integer, String>.
+     * <p>
+     * Note that only the Object class should not have a superclass and therefore
+     * return null.
+     */
+    ReferenceType getSuperClass();
+
+    /**
+     * Return all the interfaces implemented directly by this class.
+     * It does not include the interfaces implemented by superclasses or extended
+     * by the interfaces implemented.
+     */
+    List<ReferenceType> getInterfaces();
+
+    /**
+     * Get all superclasses, with all the type typeParametersValues expressed as functions of the type
+     * typeParametersValues of this declaration.
+     */
+    List<ReferenceType> getAllSuperClasses();
+
+    /**
+     * Return all the interfaces implemented by this class, either directly or indirectly, including the interfaces
+     * extended by interfaces it implements.
+     * <p>
+     * Get all interfaces, with all the type typeParametersValues expressed as functions of the type
+     * typeParametersValues of this declaration.
+     */
+    List<ReferenceType> getAllInterfaces();
+
+    ///
+    /// Constructors
+    ///
+
+    /**
+     * List of constructors available for the class.
+     * This list should also include the default constructor.
+     */
+    List<ConstructorDeclaration> getConstructors();
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ConstructorDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ConstructorDeclaration.java
new file mode 100644
index 0000000..54043a2
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ConstructorDeclaration.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * A declaration of a constructor.
+ *
+ * @author Federico Tomassetti
+ */
+public interface ConstructorDeclaration extends MethodLikeDeclaration {
+
+    @Override
+    ClassDeclaration declaringType();
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/Declaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/Declaration.java
new file mode 100644
index 0000000..38a32ff
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/Declaration.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * A generic declaration.
+ *
+ * @author Federico Tomassetti
+ */
+public interface Declaration {
+
+    /**
+     * Anonymous classes do not have a name, for example.
+     */
+    default boolean hasName() {
+        return true;
+    }
+
+    /**
+     * Should return the name or throw a RuntimeException if the name is not available.
+     */
+    String getName();
+
+    /**
+     * Does this declaration represents a class field?
+     */
+    default boolean isField() {
+        return false;
+    }
+
+    /**
+     * Does this declaration represents a method parameter?
+     */
+    default boolean isParameter() {
+        return false;
+    }
+
+    /**
+     * Does this declaration represents a type?
+     */
+    default boolean isType() {
+        return false;
+    }
+
+    /**
+     * Does this declaration represents a method?
+     */
+    default boolean isMethod() {
+        return false;
+    }
+
+    /**
+     * Return this as a FieldDeclaration or throw an UnsupportedOperationException
+     */
+    default FieldDeclaration asField() {
+        throw new UnsupportedOperationException(String.format("%s is not a FieldDeclaration", this));
+    }
+
+    /**
+     * Return this as a ParameterDeclaration or throw an UnsupportedOperationException
+     */
+    default ParameterDeclaration asParameter() {
+        throw new UnsupportedOperationException(String.format("%s is not a ParameterDeclaration", this));
+    }
+
+    /**
+     * Return this as a TypeDeclaration or throw an UnsupportedOperationException
+     */
+    default TypeDeclaration asType() {
+        throw new UnsupportedOperationException(String.format("%s is not a TypeDeclaration", this));
+    }
+
+    /**
+     * Return this as a MethodDeclaration or throw an UnsupportedOperationException
+     */
+    default MethodDeclaration asMethod() {
+        throw new UnsupportedOperationException(String.format("%s is not a MethodDeclaration", this));
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/EnumDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/EnumDeclaration.java
new file mode 100644
index 0000000..05b0d5f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/EnumDeclaration.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * Declaration of an Enum.
+ *
+ * @author Federico Tomassetti
+ */
+public interface EnumDeclaration extends ReferenceTypeDeclaration, HasAccessLevel {
+
+    @Override
+    default boolean isEnum() {
+        return true;
+    }
+
+    @Override
+    default EnumDeclaration asEnum() {
+        return this;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/FieldDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/FieldDeclaration.java
new file mode 100644
index 0000000..0281a39
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/FieldDeclaration.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * Declaration of a field.
+ *
+ * @author Federico Tomassetti
+ */
+public interface FieldDeclaration extends ValueDeclaration, HasAccessLevel {
+
+    /**
+     * Is the field static?
+     */
+    boolean isStatic();
+
+    @Override
+    default boolean isField() {
+        return true;
+    }
+
+    @Override
+    default FieldDeclaration asField() {
+        return this;
+    }
+
+    /**
+     * The type on which this field has been declared
+     */
+    TypeDeclaration declaringType();
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/HasAccessLevel.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/HasAccessLevel.java
new file mode 100644
index 0000000..3b78ea0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/HasAccessLevel.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * Anything which can have an AccessLevel.
+ *
+ * @author Federico Tomassetti
+ */
+public interface HasAccessLevel {
+
+    /**
+     * The AccessLevel of this element.
+     */
+    AccessLevel accessLevel();
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/InterfaceDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/InterfaceDeclaration.java
new file mode 100644
index 0000000..58b3da5
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/InterfaceDeclaration.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An interface declaration.
+ *
+ * @author Federico Tomassetti
+ */
+public interface InterfaceDeclaration extends ReferenceTypeDeclaration, TypeParametrizable, HasAccessLevel {
+
+    @Override
+    default boolean isInterface() {
+        return true;
+    }
+
+    /**
+     * Return the list of interfaces extended directly by this one.
+     */
+    List<ReferenceType> getInterfacesExtended();
+
+    /**
+     * Return the list of interfaces extended directly or indirectly by this one.
+     */
+    default List<ReferenceType> getAllInterfacesExtended() {
+        List<ReferenceType> interfaces = new ArrayList<>();
+        for (ReferenceType interfaceDeclaration : getInterfacesExtended()) {
+            interfaces.add(interfaceDeclaration);
+            interfaces.addAll(interfaceDeclaration.getAllInterfacesAncestors());
+        }
+        return interfaces;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodAmbiguityException.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodAmbiguityException.java
new file mode 100644
index 0000000..06c848e
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodAmbiguityException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * It is not possible to decide how to resolve a method invocation.
+ *
+ * @author Federico Tomassetti
+ */
+public class MethodAmbiguityException extends RuntimeException {
+
+    /**
+     * Create an instance from a description of the reason why there is ambiguity in this particular case.
+     */
+    public MethodAmbiguityException(String description) {
+        super(description);
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodDeclaration.java
new file mode 100644
index 0000000..fe771a4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodDeclaration.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+/**
+ * A declaration of a method (either in an interface, a class, an enum or an annotation).
+ *
+ * @author Federico Tomassetti
+ */
+public interface MethodDeclaration extends MethodLikeDeclaration {
+
+    /**
+     * The type of the value returned by the current method. This method can also be invoked
+     * for methods returning void.
+     */
+    Type getReturnType();
+
+    /**
+     * Is the method abstract? All interface methods not marked as default are abstract.
+     */
+    boolean isAbstract();
+
+    /**
+     * Is this a default method?
+     */
+    boolean isDefaultMethod();
+
+    /*
+     * Is this method static?
+     */
+    boolean isStatic();
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodLikeDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodLikeDeclaration.java
new file mode 100644
index 0000000..12f6970
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/MethodLikeDeclaration.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import java.util.Optional;
+
+/**
+ * This is a common interface for MethodDeclaration and ConstructorDeclaration.
+ *
+ * @author Federico Tomassetti
+ */
+public interface MethodLikeDeclaration extends Declaration, TypeParametrizable, HasAccessLevel {
+    /**
+     * The package name of the declaring type.
+     */
+    default String getPackageName() {
+        return declaringType().getPackageName();
+    }
+
+    /**
+     * The class(es) wrapping the declaring type.
+     */
+    default String getClassName() {
+        return declaringType().getClassName();
+    }
+
+    /**
+     * The qualified name of the method composed by the qualfied name of the declaring type
+     * followed by a dot and the name of the method.
+     */
+    default String getQualifiedName() {
+        return declaringType().getQualifiedName() + "." + this.getName();
+    }
+
+    /**
+     * The signature of the method.
+     */
+    default String getSignature() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(getName());
+        sb.append("(");
+        for (int i = 0; i < getNumberOfParams(); i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(getParam(i).describeType());
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
+    /**
+     * The qualified signature of the method. It is composed by the qualified name of the declaring type
+     * followed by the signature of the method.
+     */
+    default String getQualifiedSignature() {
+        return declaringType().getId() + "." + this.getSignature();
+    }
+
+    /**
+     * The type in which the method is declared.
+     */
+    ReferenceTypeDeclaration declaringType();
+
+    /**
+     * Number of params.
+     */
+    int getNumberOfParams();
+
+    /**
+     * Get the ParameterDeclaration at the corresponding position or throw IllegalArgumentException.
+     */
+    ParameterDeclaration getParam(int i);
+
+    /**
+     * Utility method to get the last ParameterDeclaration. It throws UnsupportedOperationException if the method
+     * has no parameters.
+     * The last parameter can be variadic and sometimes it needs to be handled in a special way.
+     */
+    default ParameterDeclaration getLastParam() {
+        if (getNumberOfParams() == 0) {
+            throw new UnsupportedOperationException("This method has no typeParametersValues, therefore it has no a last parameter");
+        }
+        return getParam(getNumberOfParams() - 1);
+    }
+
+    /**
+     * Has the method or construcor a variadic parameter?
+     * Note that when a method has a variadic parameter it should have an array type.
+     */
+    default boolean hasVariadicParameter() {
+        if (getNumberOfParams() == 0) {
+            return false;
+        } else {
+            return getParam(getNumberOfParams() - 1).isVariadic();
+        }
+    }
+
+    @Override
+    default Optional<TypeParameterDeclaration> findTypeParameter(String name) {
+        for (TypeParameterDeclaration tp : this.getTypeParameters()) {
+            if (tp.getName().equals(name)) {
+                return Optional.of(tp);
+            }
+        }
+        return declaringType().findTypeParameter(name);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ParameterDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ParameterDeclaration.java
new file mode 100644
index 0000000..27edacc
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ParameterDeclaration.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+/**
+ * Declaration of a parameter.
+ *
+ * @author Federico Tomassetti
+ */
+public interface ParameterDeclaration extends ValueDeclaration {
+
+    @Override
+    default boolean isParameter() {
+        return true;
+    }
+
+    @Override
+    default ParameterDeclaration asParameter() {
+        return this;
+    }
+
+    /**
+     * Is this parameter declared as variadic?
+     */
+    boolean isVariadic();
+
+    /**
+     * Describe the type of the parameter. In practice add three dots to the type name
+     * is the parameter is variadic.
+     */
+    default String describeType() {
+        if (isVariadic()) {
+            return getType().asArrayType().getComponentType().describe() + "...";
+        } else {
+            return getType().describe();
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ReferenceTypeDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ReferenceTypeDeclaration.java
new file mode 100644
index 0000000..76ae477
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ReferenceTypeDeclaration.java
@@ -0,0 +1,225 @@
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+public interface ReferenceTypeDeclaration extends TypeDeclaration, TypeParametrizable {
+
+    @Override
+    default ReferenceTypeDeclaration asReferenceType() {
+        return this;
+    }
+
+    ///
+    /// Ancestors
+    ///
+
+    /**
+     * The list of all the direct ancestors of the current declaration.
+     * Note that the ancestor can be parametrized types with values specified. For example:
+     * <p>
+     * class A implements Comparable&lt;String&gt; {}
+     * <p>
+     * In this case the ancestor is Comparable&lt;String&gt;
+     */
+    List<ReferenceType> getAncestors();
+
+    /**
+     * The list of all the ancestors of the current declaration, direct and indirect.
+     * This list does not contains duplicates with the exacting same type parameters.
+     */
+    default List<ReferenceType> getAllAncestors() {     
+        List<ReferenceType> ancestors = new ArrayList<>();
+        // We want to avoid infinite recursion in case of Object having Object as ancestor
+        if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) {       
+            for (ReferenceType ancestor : getAncestors()) {
+                ancestors.add(ancestor);    
+                for (ReferenceType inheritedAncestor : ancestor.getAllAncestors()) {
+                    if (!ancestors.contains(inheritedAncestor)) {
+                        ancestors.add(inheritedAncestor);
+                    }
+                }
+            }
+        }
+        return ancestors;
+    }
+
+    ///
+    /// Fields
+    ///
+
+    /**
+     * Note that the type of the field should be expressed using the type variables of this particular type.
+     * Consider for example:
+     * <p>
+     * class Foo<E> { E field; }
+     * <p>
+     * class Bar extends Foo<String> { }
+     * <p>
+     * When calling getField("field") on Foo I should get a FieldDeclaration with type E, while calling it on
+     * Bar I should get a FieldDeclaration with type String.
+     */
+    default FieldDeclaration getField(String name) {
+        Optional<FieldDeclaration> field = this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst();
+        if (field.isPresent()) {
+            return field.get();
+        } else {
+            throw new UnsolvedSymbolException("Field not found: " + name);
+        }
+    }
+
+    /**
+     * Consider only field or inherited field which is not private.
+     */
+    default FieldDeclaration getVisibleField(String name) {
+        Optional<FieldDeclaration> field = getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst();
+        if (field.isPresent()) {
+            return field.get();
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /**
+     * Has this type a field with the given name?
+     */
+    default boolean hasField(String name) {
+        return this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent();
+    }
+
+    /**
+     * Either a declared field or inherited field which is not private.
+     */
+    default boolean hasVisibleField(String name) {
+        return getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent();
+    }
+
+    /**
+     * Return a list of all fields, either declared in this declaration or inherited.
+     *
+     * Note that they could refer to inherited type variables.
+     */
+    List<FieldDeclaration> getAllFields();
+
+    /**
+     * Return a list of all fields declared and the inherited ones which are not private.
+     */
+    default List<FieldDeclaration> getVisibleFields() {
+        return getAllFields().stream()
+                .filter(f -> f.declaringType().equals(this) || f.accessLevel() != AccessLevel.PRIVATE)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Return a list of all the non static fields, either declared or inherited.
+     */
+    default List<FieldDeclaration> getAllNonStaticFields() {
+        return getAllFields().stream().filter(it -> !it.isStatic()).collect(Collectors.toList());
+    }
+
+    /**
+     * Return a list of all the static fields, either declared or inherited.
+     */
+    default List<FieldDeclaration> getAllStaticFields() {
+        return getAllFields().stream().filter(it -> it.isStatic()).collect(Collectors.toList());
+    }
+
+    /**
+     * Return a list of all the fields declared in this type.
+     */
+    default List<FieldDeclaration> getDeclaredFields() {
+        return getAllFields().stream().filter(it -> it.declaringType().getQualifiedName().equals(getQualifiedName())).collect(Collectors.toList());
+    }
+
+    ///
+    /// Methods
+    ///
+
+    /**
+     * Return a list of all the methods declared in this type declaration.
+     */
+    Set<MethodDeclaration> getDeclaredMethods();
+
+    /**
+     * Return a list of all the methods declared of this type declaration, either declared or inherited.
+     * Note that it should not include overridden methods.
+     */
+    Set<MethodUsage> getAllMethods();
+
+    ///
+    /// Assignability
+    ///
+
+    /**
+     * Can we assign instances of the given type to variables having the type defined
+     * by this declaration?
+     */
+    boolean isAssignableBy(Type type);
+
+    /**
+     * Can we assign instances of the type defined by this declaration to variables having the type defined
+     * by the given type?
+     */
+    default boolean canBeAssignedTo(ReferenceTypeDeclaration other) {
+        return other.isAssignableBy(this);
+    }
+
+    /**
+     * Can we assign instances of the given type to variables having the type defined
+     * by this declaration?
+     */
+    boolean isAssignableBy(ReferenceTypeDeclaration other);
+
+    ///
+    /// Annotations
+    ///
+
+    /**
+     * Has the type at least one annotation declared having the specified qualified name?
+     */
+    boolean hasDirectlyAnnotation(String qualifiedName);
+
+    /**
+     * Has the type at least one annotation declared or inherited having the specified qualified name?
+     */
+    default boolean hasAnnotation(String qualifiedName) {
+        if (hasDirectlyAnnotation(qualifiedName)) {
+            return true;
+        }
+        return getAllAncestors().stream().anyMatch(it -> it.asReferenceType().getTypeDeclaration().hasDirectlyAnnotation(qualifiedName));
+    }
+
+    /**
+     * This means that the type has a functional method. Conceptually, a functional interface has exactly one abstract method.
+     * Typically these classes has the FunctionInterface annotation but this is not mandatory.
+     */
+    boolean isFunctionalInterface();
+
+    ///
+    /// Type parameters
+    ///
+
+    @Override
+    default Optional<TypeParameterDeclaration> findTypeParameter(String name) {
+        for (TypeParameterDeclaration tp : this.getTypeParameters()) {
+            if (tp.getName().equals(name)) {
+                return Optional.of(tp);
+            }
+        }
+        if (this.containerType().isPresent()) {
+            return this.containerType().get().findTypeParameter(name);
+        }
+        return Optional.empty();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeDeclaration.java
new file mode 100644
index 0000000..4fd9059
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeDeclaration.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
+
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * A declaration of a type. It could be a primitive type, an enum, a class, an interface or a type variable.
+ * It cannot be an annotation or an array.
+ *
+ * @author Federico Tomassetti
+ */
+public interface TypeDeclaration extends Declaration {
+
+    ///
+    /// Containment
+    ///
+
+    /**
+     * Get the list of types defined inside the current type.
+     */
+    default Set<ReferenceTypeDeclaration> internalTypes() {
+        throw new UnsupportedOperationException("InternalTypes not available for " + this.getClass().getCanonicalName());
+    }
+
+    /**
+     * Returns a type declaration for the internal type based on name.
+     * (Does not include internal types inside internal types).
+     */
+    default ReferenceTypeDeclaration getInternalType(String name) {
+        Optional<ReferenceTypeDeclaration> type =
+                this.internalTypes().stream().filter(f -> f.getName().equals(name)).findFirst();
+        return type.orElseThrow(() ->
+                new UnsolvedSymbolException("Internal type not found: " + name));
+    }
+
+    /**
+     * Does this type contain an internal type with the given name?
+     * (Does not include internal types inside internal types).
+     */
+    default boolean hasInternalType(String name) {
+        return this.internalTypes().stream().anyMatch(f -> f.getName().equals(name));
+    }
+
+    /**
+     * Get the ReferenceTypeDeclaration enclosing this declaration.
+     *
+     * @return
+     */
+    Optional<ReferenceTypeDeclaration> containerType();
+
+    ///
+    /// Misc
+    ///
+
+    /**
+     * Is this the declaration of a class?
+     * Note that an Enum is not considered a Class in this case.
+     */
+    default boolean isClass() {
+        return false;
+    }
+
+    /**
+     * Is this the declaration of an interface?
+     */
+    default boolean isInterface() {
+        return false;
+    }
+
+    /**
+     * Is this the declaration of an enum?
+     */
+    default boolean isEnum() {
+        return false;
+    }
+
+    /**
+     * Is this the declaration of a type parameter?
+     */
+    default boolean isTypeParameter() {
+        return false;
+    }
+
+    @Override
+    default boolean isType() {
+        return true;
+    }
+
+    @Override
+    default TypeDeclaration asType() {
+        return this;
+    }
+
+    /**
+     * Return this as a ClassDeclaration or throw UnsupportedOperationException.
+     */
+    default ClassDeclaration asClass() {
+        throw new UnsupportedOperationException(String.format("%s is not a class", this));
+    }
+
+    /**
+     * Return this as a InterfaceDeclaration or throw UnsupportedOperationException.
+     */
+    default InterfaceDeclaration asInterface() {
+        throw new UnsupportedOperationException(String.format("%s is not an interface", this));
+    }
+
+    /**
+     * Return this as a EnumDeclaration or throw UnsupportedOperationException.
+     */
+    default EnumDeclaration asEnum() {
+        throw new UnsupportedOperationException(String.format("%s is not an enum", this));
+    }
+
+    /**
+     * Return this as a TypeParameterDeclaration or throw UnsupportedOperationException.
+     */
+    default TypeParameterDeclaration asTypeParameter() {
+        throw new UnsupportedOperationException(String.format("%s is not a type parameter", this));
+    }
+
+    default ReferenceTypeDeclaration asReferenceType() {
+        throw new UnsupportedOperationException(String.format("%s is not a reference type", this));
+    }
+
+    /**
+     * The package name of the type.
+     */
+    String getPackageName();
+
+    /**
+     * The class(es) wrapping this type.
+     */
+    String getClassName();
+
+    /**
+     * The fully qualified name of the type declared.
+     */
+    String getQualifiedName();
+
+    /**
+     * The ID corresponds most of the type to the qualified name. It differs only for local
+     * classes which do not have a qualified name but have an ID.
+     */
+    default String getId() {
+        String qname = getQualifiedName();
+        if (qname == null) {
+            return String.format("<localClass>:%s", getName());
+        }
+        return qname;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeParameterDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeParameterDeclaration.java
new file mode 100644
index 0000000..6cd39d0
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeParameterDeclaration.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Declaration of a type parameter.
+ * For example:
+ * <p>
+ * class A&lt;E extends String&gt;{}
+ * </p>
+ * <p>
+ * In this case <b>E</b> would be a type parameter.
+ *
+ * @author Federico Tomassetti
+ */
+public interface TypeParameterDeclaration extends TypeDeclaration {
+
+    /**
+     * Instantiate a TypeParameter defined on a Type with the given data.
+     */
+    static TypeParameterDeclaration onType(final String name, String classQName, List<Bound> bounds) {
+        return new TypeParameterDeclaration() {
+            @Override
+            public String getName() {
+                return name;
+            }
+
+            @Override
+            public boolean declaredOnType() {
+                return true;
+            }
+
+            @Override
+            public boolean declaredOnMethod() {
+                return false;
+            }
+
+            @Override
+            public boolean declaredOnConstructor() {
+                return false;
+            }
+
+            @Override
+            public String getContainerQualifiedName() {
+                return classQName;
+            }
+
+            @Override
+            public String getContainerId() {
+                return classQName;
+            }
+            
+            @Override
+            public TypeParametrizable getContainer() {
+                return null;
+            }
+
+            @Override
+            public List<Bound> getBounds(TypeSolver typeSolver) {
+                return bounds;
+            }
+
+            @Override
+            public String toString() {
+                return "TypeParameter onType " + name;
+            }
+
+            @Override
+            public Optional<ReferenceTypeDeclaration> containerType() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    /**
+     * Name of the type parameter.
+     */
+    String getName();
+
+    /**
+     * Is the type parameter been defined on a type?
+     */
+    default boolean declaredOnType() {
+        return (getContainer() instanceof ReferenceTypeDeclaration);
+    }
+
+    /**
+     * Is the type parameter been defined on a method?
+     */
+    default boolean declaredOnMethod() {
+        return (getContainer() instanceof MethodDeclaration);
+    }
+
+    /**
+     * Is the type parameter been defined on a constructor?
+     */
+    default boolean declaredOnConstructor() {
+        return (getContainer() instanceof ConstructorDeclaration);
+    }
+
+    /**
+     * The package name of the type bound(s).
+     * This is unsupported because there is no package for a Type Parameter, only for its container.
+     */
+    default String getPackageName() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * The class(es) wrapping the type bound(s).
+     * This is unsupported because there is no class for a Type Parameter, only for its container.
+     */
+    default String getClassName() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * The qualified name of the Type Parameter.
+     * It is composed by the qualified name of the container followed by a dot and the name of the Type Parameter.
+     * The qualified name of a method is its qualified signature.
+     */
+    default String getQualifiedName() {
+        return String.format("%s.%s", getContainerId(), getName());
+    }
+
+    /**
+     * The qualified name of the container.
+     */
+    String getContainerQualifiedName();
+
+    /**
+     * The ID of the container. See TypeContainer.getId
+     */
+    String getContainerId();
+    
+    /**
+     * The TypeParametrizable of the container. Can be either a ReferenceTypeDeclaration or a MethodLikeDeclaration
+     */
+    TypeParametrizable getContainer();
+
+    /**
+     * The bounds specified for the type parameter.
+     * For example:
+     * "extends A" or "super B"
+     */
+    List<Bound> getBounds(TypeSolver typeSolver);
+
+    /**
+     * A Bound on a Type Parameter.
+     */
+    class Bound {
+        private boolean extendsBound;
+        private Type type;
+
+        private Bound(boolean extendsBound, Type type) {
+            this.extendsBound = extendsBound;
+            this.type = type;
+        }
+
+        /**
+         * Create an extends bound with the given type:
+         * <p>
+         * extends "given type"
+         * </p>
+         */
+        public static Bound extendsBound(Type type) {
+            return new Bound(true, type);
+        }
+
+        /**
+         * Create a super bound with the given type:
+         * <p>
+         * super "given type"
+         * </p>
+         */
+        public static Bound superBound(Type type) {
+            return new Bound(false, type);
+        }
+
+        /**
+         * Get the type used in the Bound.
+         */
+        public Type getType() {
+            return type;
+        }
+
+        /**
+         * Is this an extends bound?
+         */
+        public boolean isExtends() {
+            return extendsBound;
+        }
+
+        /**
+         * Is this a super bound?
+         */
+        public boolean isSuper() {
+            return !isExtends();
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeParametrizable.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeParametrizable.java
new file mode 100644
index 0000000..8e9e727
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/TypeParametrizable.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * An entity which has type parameter.
+ *
+ * @author Federico Tomassetti
+ */
+public interface TypeParametrizable {
+
+    /**
+     * The list of type parameters defined on this element.
+     */
+    List<TypeParameterDeclaration> getTypeParameters();
+
+    /**
+     * Find the closest TypeParameterDeclaration with the given name.
+     * It first look on this element itself and then on the containers.
+     */
+    Optional<TypeParameterDeclaration> findTypeParameter(String name);
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ValueDeclaration.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ValueDeclaration.java
new file mode 100644
index 0000000..d291f42
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/declarations/ValueDeclaration.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.declarations;
+
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+/**
+ * Declaration of a value.
+ *
+ * @author Federico Tomassetti
+ */
+public interface ValueDeclaration extends Declaration {
+
+    /**
+     * Type of the declaration.
+     */
+    Type getType();
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/methods/MethodUsage.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/methods/MethodUsage.java
new file mode 100644
index 0000000..453c63f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/methods/MethodUsage.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.methods;
+
+import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParametersMap;
+import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParametrized;
+
+import java.util.*;
+
+/**
+ * This is basically a MethodDeclaration with some TypeParameters defined.
+ * The defined TypeParameters can comes from the Method itself or from the surrounding types.
+ *
+ * @author Federico Tomassetti
+ */
+public class MethodUsage implements TypeParametrized {
+    private MethodDeclaration declaration;
+    private List<Type> paramTypes = new ArrayList<>();
+    private Type returnType;
+    private TypeParametersMap typeParametersMap;
+
+    public MethodUsage(MethodDeclaration declaration) {
+        this.typeParametersMap = TypeParametersMap.empty();
+        this.declaration = declaration;
+        for (int i = 0; i < declaration.getNumberOfParams(); i++) {
+            paramTypes.add(declaration.getParam(i).getType());
+        }
+        returnType = declaration.getReturnType();
+    }
+
+    public MethodUsage(MethodDeclaration declaration, List<Type> paramTypes, Type returnType) {
+        this(declaration, paramTypes, returnType, TypeParametersMap.empty());
+    }
+
+    private MethodUsage(MethodDeclaration declaration, List<Type> paramTypes, Type returnType, TypeParametersMap typeParametersMap) {
+        this.declaration = declaration;
+        this.paramTypes = paramTypes;
+        this.returnType = returnType;
+        this.typeParametersMap = typeParametersMap;
+    }
+
+    @Override
+    public String toString() {
+        return "MethodUsage{" +
+                "declaration=" + declaration +
+                ", paramTypes=" + paramTypes +
+                '}';
+    }
+
+    public MethodDeclaration getDeclaration() {
+        return declaration;
+    }
+
+    public String getName() {
+        return declaration.getName();
+    }
+
+    public ReferenceTypeDeclaration declaringType() {
+        return declaration.declaringType();
+    }
+
+    public Type returnType() {
+        return returnType;
+    }
+
+    public List<Type> getParamTypes() {
+        return paramTypes;
+    }
+
+    public MethodUsage replaceParamType(int i, Type replaced) {
+        if (paramTypes.get(i) == replaced) {
+            return this;
+        }
+        List<Type> newParams = new LinkedList<>(paramTypes);
+        newParams.set(i, replaced);
+        return new MethodUsage(declaration, newParams, returnType, typeParametersMap);
+    }
+
+    public MethodUsage replaceReturnType(Type returnType) {
+        if (returnType == this.returnType) {
+            return this;
+        } else {
+            return new MethodUsage(declaration, paramTypes, returnType, typeParametersMap);
+        }
+    }
+
+    /**
+     * Return the number of formal arguments accepted by this method.
+     */
+    public int getNoParams() {
+        return paramTypes.size();
+    }
+
+    /**
+     * Return the type of the formal argument at the given position.
+     */
+    public Type getParamType(int i) {
+        return paramTypes.get(i);
+    }
+
+    public MethodUsage replaceTypeParameter(TypeParameterDeclaration typeParameter, Type type) {
+        if (type == null) {
+            throw new IllegalArgumentException();
+        }
+
+        // TODO if the method declaration has a type param with that name ignore this call
+        MethodUsage res = new MethodUsage(declaration, paramTypes, returnType, typeParametersMap.toBuilder().setValue(typeParameter, type).build());
+
+        Map<TypeParameterDeclaration, Type> inferredTypes = new HashMap<>();
+        for (int i = 0; i < paramTypes.size(); i++) {
+            Type originalParamType = paramTypes.get(i);
+            Type newParamType = originalParamType.replaceTypeVariables(typeParameter, type, inferredTypes);
+            res = res.replaceParamType(i, newParamType);
+        }
+        Type oldReturnType = res.returnType;
+        Type newReturnType = oldReturnType.replaceTypeVariables(typeParameter, type, inferredTypes);
+        res = res.replaceReturnType(newReturnType);
+        return res;
+    }
+
+    @Override
+    public TypeParametersMap typeParametersMap() {
+        return typeParametersMap;
+    }
+
+    public String getQualifiedSignature() {
+        // TODO use the type parameters
+        return this.getDeclaration().getQualifiedSignature();
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/SymbolReference.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/SymbolReference.java
new file mode 100644
index 0000000..6bab998
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/SymbolReference.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.resolution;
+
+import com.github.javaparser.symbolsolver.model.declarations.Declaration;
+
+import java.util.Optional;
+
+/**
+ * A reference to a symbol. It can solved or not solved. If solved the corresponding
+ * declaration will be provided.
+ *
+ * @author Federico Tomassetti
+ */
+public class SymbolReference<S extends Declaration> {
+
+    private Optional<? extends S> correspondingDeclaration;
+
+    private SymbolReference(Optional<? extends S> correspondingDeclaration) {
+        this.correspondingDeclaration = correspondingDeclaration;
+    }
+
+    /**
+     * Create a solve reference to the given symbol.
+     */
+    public static <S extends Declaration, S2 extends S> SymbolReference<S> solved(S2 symbolDeclaration) {
+        return new SymbolReference<S>(Optional.of(symbolDeclaration));
+    }
+
+    /**
+     * Create an unsolved reference specifying the type of the value expected.
+     */
+    public static <S extends Declaration, S2 extends S> SymbolReference<S> unsolved(Class<S2> clazz) {
+        return new SymbolReference<S>(Optional.<S>empty());
+    }
+
+    @Override
+    public String toString() {
+        return "SymbolReference{" + correspondingDeclaration + "}";
+    }
+
+    /**
+     * The corresponding declaration. If not solve this throws UnsupportedOperationException.
+     */
+    public S getCorrespondingDeclaration() {
+        if (!isSolved()) {
+            throw new UnsupportedOperationException();
+        }
+        return correspondingDeclaration.get();
+    }
+
+    /**
+     * Is the reference solved?
+     */
+    public boolean isSolved() {
+        return correspondingDeclaration.isPresent();
+    }
+
+    public static <O extends Declaration> SymbolReference<O> adapt(SymbolReference<? extends O> ref, Class<O> clazz) {
+        if (ref.isSolved()) {
+            return SymbolReference.solved(ref.getCorrespondingDeclaration());
+        } else {
+            return SymbolReference.unsolved(clazz);
+        }
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/TypeSolver.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/TypeSolver.java
new file mode 100644
index 0000000..4bd8e05
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/TypeSolver.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.resolution;
+
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+
+/**
+ * An element able to find TypeDeclaration from their name.
+ * TypeSolvers are organized in hierarchies.
+ *
+ * @author Federico Tomassetti
+ */
+public interface TypeSolver {
+
+    /**
+     * Get the root of the hierarchy of type solver.
+     */
+    default TypeSolver getRoot() {
+        if (getParent() == null) {
+            return this;
+        } else {
+            return getParent().getRoot();
+        }
+    }
+
+    /**
+     * Parent of the this TypeSolver. This can return null.
+     */
+    TypeSolver getParent();
+
+    /**
+     * Set the parent of this TypeSolver.
+     */
+    void setParent(TypeSolver parent);
+
+    /**
+     * Try to solve the type with the given name. It always return a SymbolReference which can be solved
+     * or unsolved.
+     */
+    SymbolReference<ReferenceTypeDeclaration> tryToSolveType(String name);
+
+    /**
+     * Solve the given type. Either the type is found and returned or an UnsolvedSymbolException is thrown.
+     */
+    default ReferenceTypeDeclaration solveType(String name) throws UnsolvedSymbolException {
+        SymbolReference<ReferenceTypeDeclaration> ref = tryToSolveType(name);
+        if (ref.isSolved()) {
+            return ref.getCorrespondingDeclaration();
+        } else {
+            throw new UnsolvedSymbolException(name, this);
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/UnsolvedSymbolException.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/UnsolvedSymbolException.java
new file mode 100644
index 0000000..fc6824f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/UnsolvedSymbolException.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.resolution;
+
+/**
+ * This exception is thrown when a symbol cannot be resolved.
+ *
+ * @author Federico Tomassetti
+ */
+public class UnsolvedSymbolException extends RuntimeException {
+
+    private String context;
+    private String name;
+    private TypeSolver typeSolver;
+
+    public UnsolvedSymbolException(String name, TypeSolver typeSolver) {
+        super("Unsolved symbol : " + name + " using TypeSolver " + typeSolver);
+        this.typeSolver = typeSolver;
+        this.name = name;
+    }
+
+    public UnsolvedSymbolException(String name, String context) {
+        super("Unsolved symbol in " + context + " : " + name);
+        this.context = context;
+        this.name = name;
+    }
+
+    public UnsolvedSymbolException(String name) {
+        super("Unsolved symbol : " + name);
+        this.context = "unknown";
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return "UnsolvedSymbolException{" +
+                "context='" + context + '\'' +
+                ", name='" + name + '\'' +
+                ", typeSolver=" + typeSolver +
+                '}';
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/Value.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/Value.java
new file mode 100644
index 0000000..848587a
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/resolution/Value.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.resolution;
+
+import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+
+/**
+ * Any type of value.
+ *
+ * @author Federico Tomassetti
+ */
+public class Value {
+    private Type type;
+    private String name;
+
+    public Value(Type type, String name) {
+        this.type = type;
+        this.name = name;
+    }
+
+    /**
+     * Create a Value from a ValueDeclaration.
+     */
+    public static Value from(ValueDeclaration decl) {
+        Type type = decl.getType();
+        return new Value(type, decl.getName());
+    }
+
+    @Override
+    public String toString() {
+        return "Value{" +
+                "typeUsage=" + type +
+                ", name='" + name + '\'' +
+                '}';
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/ArrayType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/ArrayType.java
new file mode 100644
index 0000000..421bec5
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/ArrayType.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+
+import java.util.Map;
+
+/**
+ * Array Type.
+ *
+ * @author Federico Tomassetti
+ */
+public class ArrayType implements Type {
+
+    private Type baseType;
+
+    public ArrayType(Type baseType) {
+        this.baseType = baseType;
+    }
+
+    ///
+    /// Object methods
+    ///
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ArrayType that = (ArrayType) o;
+
+        if (!baseType.equals(that.baseType)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return baseType.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "ArrayTypeUsage{" + baseType + "}";
+    }
+
+    ///
+    /// Type methods
+    ///
+
+    @Override
+    public ArrayType asArrayType() {
+        return this;
+    }
+
+    @Override
+    public boolean isArray() {
+        return true;
+    }
+
+    @Override
+    public String describe() {
+        return baseType.describe() + "[]";
+    }
+
+    public Type getComponentType() {
+        return baseType;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        if (other.isArray()) {
+            if (baseType.isPrimitive() && other.asArrayType().getComponentType().isPrimitive()) {
+              return baseType.equals(other.asArrayType().getComponentType());
+            }
+            return baseType.isAssignableBy(other.asArrayType().getComponentType());
+        } else if (other.isNull()) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Type replaceTypeVariables(TypeParameterDeclaration tpToReplace, Type replaced, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        Type baseTypeReplaced = baseType.replaceTypeVariables(tpToReplace, replaced, inferredTypes);
+        if (baseTypeReplaced == baseType) {
+            return this;
+        } else {
+            return new ArrayType(baseTypeReplaced);
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/LambdaConstraintType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/LambdaConstraintType.java
new file mode 100644
index 0000000..43e1547
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/LambdaConstraintType.java
@@ -0,0 +1,37 @@
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+public class LambdaConstraintType  implements Type {
+    Type bound;
+
+    public LambdaConstraintType(Type bound) {
+        this.bound = bound;
+    }
+
+    @Override
+    public String describe() {
+        return "? super " + bound.describe();
+    }
+
+    public Type getBound() {
+        return bound;
+    }
+
+    @Override
+    public boolean isConstraint() {
+        return true;
+    }
+
+    @Override
+    public LambdaConstraintType asConstraintType() {
+        return this;
+    }
+
+    public static LambdaConstraintType bound(Type bound){
+        return new LambdaConstraintType(bound);
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        return bound.isAssignableBy(other);
+    }
+}
\ No newline at end of file
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/NullType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/NullType.java
new file mode 100644
index 0000000..a401498
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/NullType.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+/**
+ * This is a virtual type used to represent null values.
+ *
+ * @author Federico Tomassetti
+ */
+public class NullType implements Type {
+
+    public static final NullType INSTANCE = new NullType();
+
+    private NullType() {
+        // prevent instantiation
+    }
+
+    @Override
+    public boolean isArray() {
+        return false;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    public boolean isNull() {
+        return true;
+    }
+
+    @Override
+    public boolean isReferenceType() {
+        return false;
+    }
+
+    @Override
+    public String describe() {
+        return "null";
+    }
+
+    @Override
+    public boolean isTypeVariable() {
+        return false;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        throw new UnsupportedOperationException("It does not make sense to assign a value to null, it can only be assigned");
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/PrimitiveType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/PrimitiveType.java
new file mode 100644
index 0000000..c96a99f
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/PrimitiveType.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * @author Federico Tomassetti
+ */
+public class PrimitiveType implements Type {
+
+    ///
+    /// Constants
+    ///
+
+    public static final PrimitiveType BYTE = new PrimitiveType("byte", Byte.class.getCanonicalName(), ImmutableList.of());
+    public static final PrimitiveType SHORT = new PrimitiveType("short", Short.class.getCanonicalName(), ImmutableList.of(BYTE));
+    public static final PrimitiveType CHAR = new PrimitiveType("char", Character.class.getCanonicalName(), ImmutableList.of());
+    public static final PrimitiveType INT = new PrimitiveType("int", Integer.class.getCanonicalName(), ImmutableList.of(BYTE, SHORT, CHAR));
+    public static final PrimitiveType LONG = new PrimitiveType("long", Long.class.getCanonicalName(), ImmutableList.of(BYTE, SHORT, INT, CHAR));
+    public static final PrimitiveType BOOLEAN = new PrimitiveType("boolean", Boolean.class.getCanonicalName(), ImmutableList.of());
+    public static final PrimitiveType FLOAT = new PrimitiveType("float", Float.class.getCanonicalName(), ImmutableList.of(LONG, INT, SHORT, BYTE, CHAR));
+    public static final PrimitiveType DOUBLE = new PrimitiveType("double", Double.class.getCanonicalName(), ImmutableList.of(FLOAT, LONG, INT, SHORT, BYTE, CHAR));
+    public static final List<PrimitiveType> ALL = ImmutableList.of(INT, BOOLEAN, LONG, CHAR, FLOAT, DOUBLE, SHORT, BYTE);
+
+    ///
+    /// Fields
+    ///
+
+    private String name;
+    private String boxTypeQName;
+    private List<PrimitiveType> promotionTypes;
+
+    private PrimitiveType(String name, String boxTypeQName, List<PrimitiveType> promotionTypes) {
+        this.name = name;
+        this.boxTypeQName = boxTypeQName;
+        this.promotionTypes = promotionTypes;
+    }
+
+    public static Type byName(String name) {
+        name = name.toLowerCase();
+        for (PrimitiveType ptu : ALL) {
+            if (ptu.describe().equals(name)) {
+                return ptu;
+            }
+        }
+        throw new IllegalArgumentException("Name " + name);
+    }
+
+    @Override
+    public String toString() {
+        return "PrimitiveTypeUsage{" +
+                "name='" + name + '\'' +
+                '}';
+    }
+
+    public PrimitiveType asPrimitive() {
+        return this;
+    }
+
+    @Override
+    public boolean isArray() {
+        return false;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return true;
+    }
+
+    @Override
+    public boolean isReferenceType() {
+        return false;
+    }
+
+    @Override
+    public String describe() {
+        return name;
+    }
+
+    @Override
+    public boolean isTypeVariable() {
+        return false;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        if (other.isPrimitive()) {
+            return this == other || promotionTypes.contains(other);
+        } else if (other.isReferenceType()) {
+            if (other.asReferenceType().getQualifiedName().equals(boxTypeQName)) {
+                return true;
+            }
+            for (PrimitiveType promotion : promotionTypes) {
+                if (other.asReferenceType().getQualifiedName().equals(promotion.boxTypeQName)) {
+                    return true;
+                }
+            }
+            return false;
+        } else if (other.isConstraint()){
+            return this.isAssignableBy(other.asConstraintType().getBound());
+        } else {
+            return false;
+        }
+    }
+
+    public String getBoxTypeQName() {
+        return boxTypeQName;
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/ReferenceType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/ReferenceType.java
new file mode 100644
index 0000000..05ff3f4
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/ReferenceType.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration.Bound;
+import com.github.javaparser.symbolsolver.model.methods.MethodUsage;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParameterValueProvider;
+import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParametersMap;
+import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParametrized;
+import javaslang.Tuple2;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * A ReferenceType like a class, an interface or an enum. Note that this type can contain also the values
+ * specified for the type parameters.
+ *
+ * @author Federico Tomassetti
+ */
+public abstract class ReferenceType implements Type, TypeParametrized, TypeParameterValueProvider {
+
+    //
+    // Fields
+    //
+
+    protected ReferenceTypeDeclaration typeDeclaration;
+    protected TypeSolver typeSolver;
+    protected TypeParametersMap typeParametersMap;
+
+    //
+    // Constructors
+    //
+
+    public ReferenceType(ReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver) {
+        this(typeDeclaration, deriveParams(typeDeclaration), typeSolver);
+    }
+
+    public ReferenceType(ReferenceTypeDeclaration typeDeclaration, List<Type> typeParameters, TypeSolver typeSolver) {
+        if (typeSolver == null) {
+            throw new IllegalArgumentException("typeSolver should not be null");
+        }
+        if (typeDeclaration.isTypeParameter()) {
+            throw new IllegalArgumentException("You should use only Classes, Interfaces and enums");
+        }
+        if (typeParameters.size() > 0 && typeParameters.size() != typeDeclaration.getTypeParameters().size()) {
+            throw new IllegalArgumentException(String.format("expected either zero type parameters or has many as defined in the declaration (%d). Found %d",
+                    typeDeclaration.getTypeParameters().size(), typeParameters.size()));
+        }
+        TypeParametersMap.Builder typeParametersMapBuilder = new TypeParametersMap.Builder();
+        for (int i = 0; i < typeParameters.size(); i++) {
+            typeParametersMapBuilder.setValue(typeDeclaration.getTypeParameters().get(i), typeParameters.get(i));
+        }
+        this.typeParametersMap = typeParametersMapBuilder.build();
+        this.typeDeclaration = typeDeclaration;
+        this.typeSolver = typeSolver;
+    }
+
+    //
+    // Public Object methods
+    //
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ReferenceType that = (ReferenceType) o;
+
+        if (!typeDeclaration.equals(that.typeDeclaration)) return false;
+        if (!typeParametersMap.equals(that.typeParametersMap)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = typeDeclaration.hashCode();
+        result = 31 * result + typeParametersMap.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "ReferenceType{" + getQualifiedName() +
+                ", typeParametersMap=" + typeParametersMap +
+                '}';
+    }
+
+    ///
+    /// Relation with other types
+    ///
+
+    @Override
+    public final boolean isReferenceType() {
+        return true;
+    }
+
+    ///
+    /// Downcasting
+    ///
+
+    @Override
+    public ReferenceType asReferenceType() {
+        return this;
+    }
+
+    ///
+    /// Naming
+    ///
+
+    @Override
+    public String describe() {
+        StringBuilder sb = new StringBuilder();
+        if (hasName()) {
+            sb.append(typeDeclaration.getQualifiedName());
+        } else {
+            sb.append("<anonymous class>");
+        }
+        if (!typeParametersMap().isEmpty()) {
+            sb.append("<");
+            sb.append(String.join(", ", typeDeclaration.getTypeParameters().stream()
+                    .map(tp -> typeParametersMap().getValue(tp).describe())
+                    .collect(Collectors.toList())));
+            sb.append(">");
+        }
+        return sb.toString();
+    }
+
+    ///
+    /// TypeParameters
+    ///
+
+    /**
+     * Execute a transformation on all the type parameters of this element.
+     */
+    public Type transformTypeParameters(TypeTransformer transformer) {
+        Type result = this;
+        int i = 0;
+        for (Type tp : this.typeParametersValues()) {
+            Type transformedTp = transformer.transform(tp);
+            // Identity comparison on purpose
+            if (transformedTp != tp) {
+                List<Type> typeParametersCorrected = result.asReferenceType().typeParametersValues();
+                typeParametersCorrected.set(i, transformedTp);
+                result = create(typeDeclaration, typeParametersCorrected, typeSolver);
+            }
+            i++;
+        }
+        return result;
+    }
+
+    @Override
+    public Type replaceTypeVariables(TypeParameterDeclaration tpToReplace, Type replaced, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        if (replaced == null) {
+            throw new IllegalArgumentException();
+        }
+
+        ReferenceType result = this;
+        int i = 0;
+        for (Type tp : this.typeParametersValues()) {
+            Type transformedTp = tp.replaceTypeVariables(tpToReplace, replaced, inferredTypes);
+            // Identity comparison on purpose
+            if (tp.isTypeVariable() && tp.asTypeVariable().describe().equals(tpToReplace.getName())) {
+                inferredTypes.put(tp.asTypeParameter(), replaced);
+            }
+            if (true) {
+                List<Type> typeParametersCorrected = result.asReferenceType().typeParametersValues();
+                typeParametersCorrected.set(i, transformedTp);
+                result = create(typeDeclaration, typeParametersCorrected, typeSolver);
+            }
+            i++;
+        }
+
+        List<Type> values = result.typeParametersValues();
+        if(values.contains(tpToReplace)){
+            int index = values.indexOf(tpToReplace);
+            values.set(index, replaced);
+            return create(result.getTypeDeclaration(), values, typeSolver);
+        }
+
+
+        return result;
+    }
+
+    ///
+    /// Assignability
+    ///
+
+    /**
+     * This method checks if ThisType t = new OtherType() would compile.
+     */
+    @Override
+    public abstract boolean isAssignableBy(Type other);
+
+    ///
+    /// Ancestors
+    ///
+
+    /**
+     * Return all ancestors, that means all superclasses and interfaces.
+     * This list should always include Object (unless this is a reference to Object).
+     * The type typeParametersValues should be expressed in terms of this type typeParametersValues.
+     * <p>
+     * For example, given:
+     * <p>
+     * class Foo&lt;A, B&gt; {}
+     * class Bar&lt;C&gt; extends Foo&lt;C, String&gt; {}
+     * <p>
+     * a call to getAllAncestors on a reference to Bar having type parameter Boolean should include
+     * Foo&lt;Boolean, String&gt;.
+     */
+    public List<ReferenceType> getAllAncestors() {
+        // We need to go through the inheritance line and propagate the type parametes
+
+        List<ReferenceType> ancestors = typeDeclaration.getAllAncestors();
+
+        ancestors = ancestors.stream()
+                .map(a -> typeParametersMap().replaceAll(a).asReferenceType())
+                .collect(Collectors.toList());
+
+        // Avoid repetitions of Object
+        ancestors.removeIf(a -> a.getQualifiedName().equals(Object.class.getCanonicalName()));
+        ReferenceTypeDeclaration objectType = typeSolver.solveType(Object.class.getCanonicalName());
+        ReferenceType objectRef = create(objectType, typeSolver);
+        ancestors.add(objectRef);
+        return ancestors;
+    }
+
+    public final List<ReferenceType> getAllInterfacesAncestors() {
+        return getAllAncestors().stream()
+                .filter(it -> it.getTypeDeclaration().isInterface())
+                .collect(Collectors.toList());
+    }
+
+    public final List<ReferenceType> getAllClassesAncestors() {
+        return getAllAncestors().stream()
+                .filter(it -> it.getTypeDeclaration().isClass())
+                .collect(Collectors.toList());
+    }
+
+    ///
+    /// Type parameters
+    ///
+
+    /**
+     * Get the type associated with the type parameter with the given name.
+     * It returns Optional.empty unless the type declaration declares a type parameter with the given name.
+     */
+    public Optional<Type> getGenericParameterByName(String name) {
+        for (TypeParameterDeclaration tp : typeDeclaration.getTypeParameters()) {
+            if (tp.getName().equals(name)) {
+                return Optional.of(this.typeParametersMap().getValue(tp));
+            }
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Get the values for all type parameters declared on this type.
+     * The list can be empty for raw types.
+     */
+    public List<Type> typeParametersValues() {
+        return this.typeParametersMap.isEmpty() ? Collections.emptyList() : typeDeclaration.getTypeParameters().stream().map(tp -> typeParametersMap.getValue(tp)).collect(Collectors.toList());
+    }
+
+    /**
+     * Get the values for all type parameters declared on this type.
+     * In case of raw types the values correspond to TypeVariables.
+     */
+    public List<Tuple2<TypeParameterDeclaration, Type>> getTypeParametersMap() {
+        List<Tuple2<TypeParameterDeclaration, Type>> typeParametersMap = new ArrayList<>();
+        if (!isRawType()) {
+	        for (int i = 0; i < typeDeclaration.getTypeParameters().size(); i++) {
+	            typeParametersMap.add(new Tuple2<>(typeDeclaration.getTypeParameters().get(0), typeParametersValues().get(i)));
+	        }
+        }
+        return typeParametersMap;
+    }
+
+    @Override
+    public TypeParametersMap typeParametersMap() {
+        return typeParametersMap;
+    }
+
+    ///
+    /// Other methods introduced by ReferenceType
+    ///
+
+    /**
+     * Corresponding TypeDeclaration
+     */
+    public final ReferenceTypeDeclaration getTypeDeclaration() {
+        return typeDeclaration;
+    }
+
+    /**
+     * The type of the field could be different from the one in the corresponding FieldDeclaration because
+     * type variables would be solved.
+     */
+    public Optional<Type> getFieldType(String name) {
+        if (!typeDeclaration.hasField(name)) {
+            return Optional.empty();
+        }
+        Type type = typeDeclaration.getField(name).getType();
+        type = useThisTypeParametersOnTheGivenType(type);
+        return Optional.of(type);
+    }
+
+    /**
+     * Has the TypeDeclaration a name? Anonymous classes do not have one.
+     */
+    public boolean hasName() {
+        return typeDeclaration.hasName();
+    }
+
+    /**
+     * Qualified name of the declaration.
+     */
+    public String getQualifiedName() {
+        return typeDeclaration.getQualifiedName();
+    }
+
+    /**
+     * Id of the declaration. It corresponds to the qualified name, unless for local classes.
+     */
+    public String getId() {
+        return typeDeclaration.getId();
+    }
+
+    /**
+     * Methods declared on this type.
+     */
+    public abstract Set<MethodUsage> getDeclaredMethods();
+
+    public boolean isRawType() {
+        if (!typeDeclaration.getTypeParameters().isEmpty()) {
+            if (typeParametersMap().isEmpty()) {
+                return true;
+            }
+            for (String name : typeParametersMap().getNames()) {
+                Optional<Type> value = typeParametersMap().getValueBySignature(name);
+                if (value.isPresent() && value.get().isTypeVariable() && value.get().asTypeVariable().qualifiedName().equals(name)) {
+                    // nothing to do
+                } else {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public Optional<Type> typeParamValue(TypeParameterDeclaration typeParameterDeclaration) {
+        if (typeParameterDeclaration.declaredOnMethod()) {
+            throw new IllegalArgumentException();
+        }
+        String typeId = this.getTypeDeclaration().getId();
+        if (typeId.equals(typeParameterDeclaration.getContainerId())) {
+            return Optional.of(this.typeParametersMap().getValue(typeParameterDeclaration));
+        }
+        for (ReferenceType ancestor : this.getAllAncestors()) {
+            if (ancestor.getId().equals(typeParameterDeclaration.getContainerId())) {
+                return Optional.of(ancestor.typeParametersMap().getValue(typeParameterDeclaration));
+            }
+        }
+        return Optional.empty();
+    }
+
+    //
+    // Protected methods
+    //
+
+    protected abstract ReferenceType create(ReferenceTypeDeclaration typeDeclaration, List<Type> typeParameters, TypeSolver typeSolver);
+
+    protected ReferenceType create(ReferenceTypeDeclaration typeDeclaration, TypeParametersMap typeParametersMap, TypeSolver typeSolver) {
+        return create(typeDeclaration, typeDeclaration.getTypeParameters().stream()
+                .map(tp -> typeParametersMap.getValue(tp))
+                .collect(Collectors.toList()), typeSolver);
+    }
+
+    protected abstract ReferenceType create(ReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver);
+
+    protected boolean isCorrespondingBoxingType(String typeName) {
+        switch (typeName) {
+            case "boolean":
+                return getQualifiedName().equals(Boolean.class.getCanonicalName());
+            case "char":
+                return getQualifiedName().equals(Character.class.getCanonicalName());
+            case "byte":
+                return getQualifiedName().equals(Byte.class.getCanonicalName());
+            case "short":
+                return getQualifiedName().equals(Short.class.getCanonicalName());
+            case "int":
+                return getQualifiedName().equals(Integer.class.getCanonicalName());
+            case "long":
+                return getQualifiedName().equals(Long.class.getCanonicalName());
+            case "float":
+                return getQualifiedName().equals(Float.class.getCanonicalName());
+            case "double":
+                return getQualifiedName().equals(Double.class.getCanonicalName());
+            default:
+                throw new UnsupportedOperationException(typeName);
+        }
+    }
+
+    protected boolean compareConsideringTypeParameters(ReferenceType other) {
+        if (other.equals(this)) {
+            return true;
+        }
+        if (this.getQualifiedName().equals(other.getQualifiedName())) {
+            if (this.isRawType() || other.isRawType()) {
+                return true;
+            }
+            if (this.typeParametersValues().size() != other.typeParametersValues().size()) {
+                throw new IllegalStateException();
+            }
+            for (int i = 0; i < typeParametersValues().size(); i++) {
+                Type thisParam = typeParametersValues().get(i);
+                Type otherParam = other.typeParametersValues().get(i);
+                if (!thisParam.equals(otherParam)) {
+                    if (thisParam instanceof Wildcard) {
+                        Wildcard thisParamAsWildcard = (Wildcard) thisParam;
+                        if (thisParamAsWildcard.isSuper() && otherParam.isAssignableBy(thisParamAsWildcard.getBoundedType())) {
+                            // ok
+                        } else if (thisParamAsWildcard.isExtends() && thisParamAsWildcard.getBoundedType().isAssignableBy(otherParam)) {
+                            // ok
+                        } else if (!thisParamAsWildcard.isBounded()) {
+                            // ok
+                        } else {
+                            return false;
+                        }
+                    } else {
+                        if (thisParam instanceof TypeVariable && otherParam instanceof TypeVariable) {
+                            List<Type> thisBounds = thisParam.asTypeVariable().asTypeParameter().getBounds(this.typeSolver).stream().map(bound -> bound.getType()).collect(Collectors.toList());
+                            List<Type> otherBounds = otherParam.asTypeVariable().asTypeParameter().getBounds(other.typeSolver).stream().map(bound -> bound.getType()).collect(Collectors.toList());
+                            if (thisBounds.size() == otherBounds.size() && otherBounds.containsAll(thisBounds)) {
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    //
+    // Private methods
+    //
+
+    private static List<Type> deriveParams(ReferenceTypeDeclaration typeDeclaration) {
+        return typeDeclaration.getTypeParameters().stream().map((tp) -> new TypeVariable(tp)).collect(Collectors.toList());
+    }
+
+    public ReferenceType deriveTypeParameters(TypeParametersMap typeParametersMap) {
+        return create(typeDeclaration, typeParametersMap, typeSolver);
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/Type.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/Type.java
new file mode 100644
index 0000000..38f490b
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/Type.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A usage of a type. It could be a primitive type or a reference type (enum, class, interface). In the later case it
+ * could take type typeParametersValues (other TypeUsages). It could also be a TypeVariable, like in:
+ * <p>
+ * class A&lt;Bgt; { }
+ * <p>
+ * where B is a TypeVariable. It could also be Wildcard Type, possibly with constraints.
+ *
+ * @author Federico Tomassetti
+ */
+public interface Type {
+
+    ///
+    /// Relation with other types
+    ///
+
+    /**
+     * Does this type represent an array?
+     */
+    default boolean isArray() {
+        return false;
+    }
+
+    default int arrayLevel() {
+        if (isArray()) {
+            return 1 + this.asArrayType().getComponentType().arrayLevel();
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * Is this a primitive type?
+     */
+    default boolean isPrimitive() {
+        return false;
+    }
+
+    /**
+     * Is this the null type?
+     */
+    default boolean isNull() {
+        return false;
+    }
+
+    /**
+     * Is this a non primitive value?
+     */
+    default boolean isReference() {
+        return isReferenceType() || isArray() || isTypeVariable() || isNull() || isWildcard();
+    }
+
+    /**
+     * Is this a lambda constraint type?
+     */
+    default boolean isConstraint() { return false; }
+
+    /**
+     * Can this be seen as a ReferenceTypeUsage?
+     * In other words: is this a reference to a class, an interface or an enum?
+     */
+    default boolean isReferenceType() {
+        return false;
+    }
+
+    default boolean isVoid() {
+        return false;
+    }
+
+    default boolean isTypeVariable() {
+        return false;
+    }
+
+    default boolean isWildcard() {
+        return false;
+    }
+
+    ///
+    /// Downcasting
+    ///
+
+    default ArrayType asArrayType() {
+        throw new UnsupportedOperationException(String.format("%s is not an Array", this));
+    }
+
+    default ReferenceType asReferenceType() {
+        throw new UnsupportedOperationException(String.format("%s is not a Reference Type", this));
+    }
+
+    default TypeParameterDeclaration asTypeParameter() {
+        throw new UnsupportedOperationException(String.format("%s is not a Type parameter", this));
+    }
+
+    default TypeVariable asTypeVariable() {
+        throw new UnsupportedOperationException(String.format("%s is not a Type variable", this));
+    }
+
+    default PrimitiveType asPrimitive() {
+        throw new UnsupportedOperationException(String.format("%s is not a Primitive type", this));
+    }
+
+    default Wildcard asWildcard() {
+        throw new UnsupportedOperationException(String.format("%s is not a Wildcard", this));
+    }
+
+    default LambdaConstraintType asConstraintType() {
+        throw new UnsupportedOperationException(String.format("%s is not a constraint type", this));
+    }
+
+    ///
+    /// Naming
+    ///
+
+    String describe();
+
+    ///
+    /// TypeParameters
+    ///
+
+    /**
+     * Replace all variables referring to the given TypeParameter with the given value.
+     * By replacing these values I could also infer some type equivalence.
+     * Those would be collected in the given map.
+     */
+    default Type replaceTypeVariables(TypeParameterDeclaration tp, Type replaced, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        return this;
+    }
+
+    /**
+     * This is like ({@link #replaceTypeVariables(TypeParameterDeclaration, Type, Map)} but ignores the inferred values.
+     */
+    default Type replaceTypeVariables(TypeParameterDeclaration tp, Type replaced) {
+        return replaceTypeVariables(tp, replaced, new HashMap<>());
+    }
+
+    ///
+    /// Assignability
+    ///
+
+    /**
+     * This method checks if ThisType t = new OtherType() would compile.
+     */
+    boolean isAssignableBy(Type other);
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/TypeTransformer.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/TypeTransformer.java
new file mode 100644
index 0000000..60b5b76
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/TypeTransformer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+/**
+ * @author Federico Tomassetti
+ */
+@FunctionalInterface
+public interface TypeTransformer {
+    Type transform(Type type);
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/TypeVariable.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/TypeVariable.java
new file mode 100644
index 0000000..c18eff6
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/TypeVariable.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+
+import java.util.Map;
+
+/**
+ * From JLS 4.4: A type variable is introduced by the declaration of a type parameter of a generic class,
+ * interface, method, or constructor (§8.1.2, §9.1.2, §8.4.4, §8.8.4).
+ *
+ * @author Federico Tomassetti
+ */
+public class TypeVariable implements Type {
+
+    private TypeParameterDeclaration typeParameter;
+
+    public TypeVariable(TypeParameterDeclaration typeParameter) {
+        this.typeParameter = typeParameter;
+    }
+
+    @Override
+    public String toString() {
+        return "TypeVariable {" + typeParameter.getQualifiedName() + "}";
+    }
+
+    public String qualifiedName() {
+        return this.typeParameter.getQualifiedName();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        TypeVariable that = (TypeVariable) o;
+
+        if (!typeParameter.getName().equals(that.typeParameter.getName())) return false;
+        if (typeParameter.declaredOnType() != that.typeParameter.declaredOnType()) return false;
+        if (typeParameter.declaredOnMethod() != that.typeParameter.declaredOnMethod()) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return typeParameter.hashCode();
+    }
+
+    @Override
+    public boolean isArray() {
+        return false;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Type replaceTypeVariables(TypeParameterDeclaration tpToBeReplaced, Type replaced, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        if(tpToBeReplaced.getName().equals(this.typeParameter.getName())){
+            inferredTypes.put(this.asTypeParameter(), replaced);
+            return replaced;
+        } else {
+            return this;
+        }
+    }
+
+    @Override
+    public boolean isReferenceType() {
+        return false;
+    }
+
+    @Override
+    public String describe() {
+        return typeParameter.getName();
+    }
+
+    @Override
+    public TypeParameterDeclaration asTypeParameter() {
+        return typeParameter;
+    }
+
+    @Override
+    public TypeVariable asTypeVariable() {
+        return this;
+    }
+
+    @Override
+    public boolean isTypeVariable() {
+        return true;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        if (other.isTypeVariable()) {
+            return describe().equals(other.describe());
+        } else {
+            return true;
+        }
+    }
+
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/VoidType.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/VoidType.java
new file mode 100644
index 0000000..2c26e96
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/VoidType.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+/**
+ * The special type void.
+ *
+ * @author Federico Tomassetti
+ */
+public class VoidType implements Type {
+    public static final Type INSTANCE = new VoidType();
+
+    private VoidType() {
+    }
+
+    @Override
+    public String describe() {
+        return "void";
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isVoid() {
+        return true;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/Wildcard.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/Wildcard.java
new file mode 100644
index 0000000..a501290
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/Wildcard.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+
+import java.util.Map;
+
+/**
+ * A wildcard can be:
+ * - unbounded (?)
+ * - have a lower bound (? super Number)
+ * - have an upper bound (? extends Number)
+ * It is not possible to have both a lower and an upper bound at the same time.
+ *
+ * @author Federico Tomassetti
+ */
+public class Wildcard implements Type {
+
+    public static Wildcard UNBOUNDED = new Wildcard(null, null);
+
+    private BoundType type;
+    private Type boundedType;
+
+    private Wildcard(BoundType type, Type boundedType) {
+        if (type == null && boundedType != null) {
+            throw new IllegalArgumentException();
+        }
+        if (type != null && boundedType == null) {
+            throw new IllegalArgumentException();
+        }
+        this.type = type;
+        this.boundedType = boundedType;
+    }
+
+    public static Wildcard superBound(Type type) {
+        return new Wildcard(BoundType.SUPER, type);
+    }
+
+    public static Wildcard extendsBound(Type type) {
+        return new Wildcard(BoundType.EXTENDS, type);
+    }
+
+    @Override
+    public String toString() {
+        return "WildcardUsage{" +
+                "type=" + type +
+                ", boundedType=" + boundedType +
+                '}';
+    }
+
+    public boolean isWildcard() {
+        return true;
+    }
+
+    public Wildcard asWildcard() {
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof Wildcard)) return false;
+
+        Wildcard that = (Wildcard) o;
+
+        if (boundedType != null ? !boundedType.equals(that.boundedType) : that.boundedType != null) return false;
+        if (type != that.type) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = type != null ? type.hashCode() : 0;
+        result = 31 * result + (boundedType != null ? boundedType.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String describe() {
+        if (type == null) {
+            return "?";
+        } else if (type == BoundType.SUPER) {
+            return "? super " + boundedType.describe();
+        } else if (type == BoundType.EXTENDS) {
+            return "? extends " + boundedType.describe();
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public boolean isSuper() {
+        return type == BoundType.SUPER;
+    }
+
+    public boolean isExtends() {
+        return type == BoundType.EXTENDS;
+    }
+
+    public boolean isBounded() {
+        return isSuper() || isExtends();
+    }
+
+    public Type getBoundedType() {
+        if (boundedType == null) {
+            throw new IllegalStateException();
+        }
+        return boundedType;
+    }
+
+    @Override
+    public boolean isAssignableBy(Type other) {
+        if (boundedType == null) {
+            //return other.isReferenceType() && other.asReferenceType().getQualifiedName().equals(Object.class.getCanonicalName());
+            return false;
+        } else if (type == BoundType.SUPER) {
+            return boundedType.isAssignableBy(other);
+        } else if (type == BoundType.EXTENDS) {
+            return false;
+        } else {
+            throw new RuntimeException();
+        }
+    }
+
+    @Override
+    public Type replaceTypeVariables(TypeParameterDeclaration tpToReplace, Type replaced, Map<TypeParameterDeclaration, Type> inferredTypes) {
+        if (replaced == null) {
+            throw new IllegalArgumentException();
+        }
+        if (boundedType == null) {
+            return this;
+        }
+        Type boundedTypeReplaced = boundedType.replaceTypeVariables(tpToReplace, replaced, inferredTypes);
+        if (boundedTypeReplaced == null) {
+            throw new RuntimeException();
+        }
+        if (boundedTypeReplaced != boundedType) {
+            return new Wildcard(type, boundedTypeReplaced);
+        } else {
+            return this;
+        }
+    }
+
+    public enum BoundType {
+        SUPER,
+        EXTENDS
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParameterValueProvider.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParameterValueProvider.java
new file mode 100644
index 0000000..d09a583
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParameterValueProvider.java
@@ -0,0 +1,51 @@
+package com.github.javaparser.symbolsolver.model.typesystem.parametrization;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.Wildcard;
+
+import java.util.Optional;
+
+/**
+ * @author Federico Tomassetti
+ */
+public interface TypeParameterValueProvider {
+
+    /**
+     * Calculate the value for the given type parameter.
+     * It could be inherited.
+     */
+    Optional<Type> typeParamValue(TypeParameterDeclaration typeParameterDeclaration);
+
+    /**
+     * Replace the type typeParametersValues present in the given type with the ones for which this type
+     * has a value.
+     */
+    default Type useThisTypeParametersOnTheGivenType(Type type) {
+        if (type.isTypeVariable()) {
+            TypeParameterDeclaration typeParameter = type.asTypeParameter();
+            if (typeParameter.declaredOnType()) {
+                Optional<Type> typeParam = typeParamValue(typeParameter);
+                if (typeParam.isPresent()) {
+                    type = typeParam.get();
+                }
+            }
+        }
+
+        if (type.isWildcard() && type.asWildcard().isBounded()) {
+            if (type.asWildcard().isExtends()) {
+                return Wildcard.extendsBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType()));
+            } else {
+                return Wildcard.superBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType()));
+            }
+        }
+
+        if (type.isReferenceType()) {
+            type = type.asReferenceType().transformTypeParameters(tp -> useThisTypeParametersOnTheGivenType(tp));
+        }
+
+        return type;
+    }
+
+    Optional<Type> getGenericParameterByName(String name);
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametersMap.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametersMap.java
new file mode 100644
index 0000000..b73dbc1
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametersMap.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem.parametrization;
+
+import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
+import com.github.javaparser.symbolsolver.model.typesystem.Type;
+import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
+
+import java.util.*;
+
+/**
+ * A map of values associated to TypeParameters.
+ *
+ * @author Federico Tomassetti
+ */
+public class TypeParametersMap {
+
+    public static class Builder {
+        private Map<String, Type> nameToValue;
+        private Map<String, TypeParameterDeclaration> nameToDeclaration;
+
+        public Builder() {
+            nameToValue = new HashMap<>();
+            nameToDeclaration = new HashMap<>();
+        }
+
+        private Builder(Map<String, Type> nameToValue, Map<String, TypeParameterDeclaration> nameToDeclaration) {
+            this.nameToValue = new HashMap<>();
+            this.nameToValue.putAll(nameToValue);
+            this.nameToDeclaration = new HashMap<>();
+            this.nameToDeclaration.putAll(nameToDeclaration);
+        }
+
+        public TypeParametersMap build() {
+            return new TypeParametersMap(nameToValue, nameToDeclaration);
+        }
+
+        public Builder setValue(TypeParameterDeclaration typeParameter, Type value) {
+            // TODO: we shouldn't just silently overwrite existing types!
+            String qualifiedName = typeParameter.getQualifiedName();
+            nameToValue.put(qualifiedName, value);
+            nameToDeclaration.put(qualifiedName, typeParameter);
+            return this;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof TypeParametersMap)) return false;
+
+        TypeParametersMap that = (TypeParametersMap) o;
+
+        return nameToValue.equals(that.nameToValue) && nameToDeclaration.equals(that.nameToDeclaration);
+
+    }
+
+    @Override
+    public int hashCode() {
+        return nameToValue.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "TypeParametersMap{" +
+                "nameToValue=" + nameToValue +
+                '}';
+    }
+
+    private Map<String, Type> nameToValue;
+    private Map<String, TypeParameterDeclaration> nameToDeclaration;
+
+    public static TypeParametersMap empty() {
+        return new Builder().build();
+    }
+
+    private TypeParametersMap(Map<String, Type> nameToValue, Map<String, TypeParameterDeclaration> nameToDeclaration) {
+        this.nameToValue = new HashMap<>();
+        this.nameToValue.putAll(nameToValue);
+        this.nameToDeclaration = new HashMap<>();
+        this.nameToDeclaration.putAll(nameToDeclaration);
+    }
+
+    public Type getValue(TypeParameterDeclaration typeParameter) {
+        String qualifiedName = typeParameter.getQualifiedName();
+        if (nameToValue.containsKey(qualifiedName)) {
+            return nameToValue.get(qualifiedName);
+        } else {
+            return new TypeVariable(typeParameter);
+        }
+    }
+
+    public Optional<Type> getValueBySignature(String signature) {
+        if (nameToValue.containsKey(signature)) {
+            return Optional.of(nameToValue.get(signature));
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    public List<String> getNames(){
+        return new ArrayList<>(nameToValue.keySet());
+    }
+
+    public List<Type> getTypes(){
+        return new ArrayList<>(nameToValue.values());
+    }
+
+    public Builder toBuilder() {
+        return new Builder(nameToValue, nameToDeclaration);
+    }
+
+    public boolean isEmpty() {
+        return nameToValue.isEmpty();
+    }
+
+    public Type replaceAll(Type type) {
+        Map<TypeParameterDeclaration, Type> inferredTypes = new HashMap<>();
+        for (TypeParameterDeclaration typeParameterDeclaration : this.nameToDeclaration.values()) {
+            type = type.replaceTypeVariables(typeParameterDeclaration, getValue(typeParameterDeclaration), inferredTypes);
+        }
+        return type;
+    }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametrized.java b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametrized.java
new file mode 100644
index 0000000..ed0736d
--- /dev/null
+++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/src/java-symbol-solver-model/com/github/javaparser/symbolsolver/model/typesystem/parametrization/TypeParametrized.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016 Federico Tomassetti
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.javaparser.symbolsolver.model.typesystem.parametrization;
+
+/**
+ * Something which can have values for TypeParameters.
+ *
+ * @author Federico Tomassetti
+ */
+public interface TypeParametrized {
+    TypeParametersMap typeParametersMap();
+}
diff --git a/javaparser-testing/javaparser-testing.iml b/javaparser-testing/javaparser-testing.iml
deleted file mode 100644
index 6130e1a..0000000
--- a/javaparser-testing/javaparser-testing.iml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
-    <output url="file://$MODULE_DIR$/target/classes" />
-    <output-test url="file://$MODULE_DIR$/target/test-classes" />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="javaparser-core" scope="TEST" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.0.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.0.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.0.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.0.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.jbehave:jbehave-core:4.1.2" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-integration:1.3" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.apache.commons:commons-collections4:4.1" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: commons-io:commons-io:2.5" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.apache.commons:commons-lang3:3.4" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.codehaus.plexus:plexus-utils:3.0.22" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.freemarker:freemarker:2.3.23" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.thoughtworks.paranamer:paranamer:2.8" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.thoughtworks.xstream:xstream:1.4.9" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: xmlpull:xmlpull:1.1.3.1" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: xpp3:xpp3_min:1.1.4c" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.google.code.gson:gson:2.8.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.github.valfirst:jbehave-junit-runner:2.1.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.6.2" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.squareup.okhttp3:okhttp:3.6.0" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.squareup.okio:okio:1.11.0" level="project" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/javaparser-testing/pom.xml b/javaparser-testing/pom.xml
deleted file mode 100644
index 7a3a458..0000000
--- a/javaparser-testing/pom.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<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.5.16-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>javaparser-testing</artifactId>
-    <description>The test suite for javaparser-core</description>
-
-    <licenses>
-        <license>
-            <name>GNU Lesser General Public License</name>
-            <url>http://www.gnu.org/licenses/lgpl-3.0.html</url>
-            <distribution>repo</distribution>
-        </license>
-        <license>
-            <name>Apache License, Version 2.0</name>
-            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-            <distribution>repo</distribution>
-            <comments>A business-friendly OSS license</comments>
-        </license>
-    </licenses>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.jacoco</groupId>
-                <artifactId>jacoco-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>jacoco-initialize</id>
-                        <goals>
-                            <goal>prepare-agent</goal>
-                        </goals>
-                    </execution>
-                    <execution>
-                        <id>jacoco-site</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>report</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <artifactId>maven-resources-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>copy-resources</id>
-                        <phase>pre-integration-test</phase>
-                        <goals>
-                            <goal>copy-resources</goal>
-                        </goals>
-                        <configuration>
-                            <encoding>UTF-8</encoding>
-                            <outputDirectory>${basedir}/target/classes</outputDirectory>
-                            <resources>
-                                <resource>
-                                    <directory>../javaparser-core/target/classes</directory>
-                                    <filtering>false</filtering>
-                                </resource>
-                            </resources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <!-- no need to release this module -->
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-    <dependencies>
-        <dependency>
-            <groupId>com.github.javaparser</groupId>
-            <artifactId>javaparser-core</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jbehave</groupId>
-            <artifactId>jbehave-core</artifactId>
-            <version>4.1.2</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.github.valfirst</groupId>
-            <artifactId>jbehave-junit-runner</artifactId>
-            <version>2.1.0</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
-            <version>3.6.2</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.squareup.okhttp3</groupId>
-            <artifactId>okhttp</artifactId>
-            <version>3.6.0</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/CommentsInserterTest.java b/javaparser-testing/src/test/java/com/github/javaparser/CommentsInserterTest.java
deleted file mode 100644
index c44a63f..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/CommentsInserterTest.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.comments.CommentsCollection;
-import org.junit.Test;
-
-import java.io.IOException;
-
-import static com.github.javaparser.JavaParser.*;
-import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class CommentsInserterTest {
-    private String makeFilename(String sampleName) {
-        return "com/github/javaparser/issue_samples/" + sampleName + ".java.txt";
-    }
-
-    private ParseResult<CompilationUnit> parseSample(String sampleName) throws IOException {
-        Provider p = Providers.resourceProvider(
-                makeFilename(sampleName));
-        return new JavaParser().parse(ParseStart.COMPILATION_UNIT, p);
-    }
-
-    /**
-     * Issue: "When there is a String constant "\\" compilationUnit ignores all further comments"
-     */
-    @Test
-    public void issue290() throws IOException {
-        ParseResult result = parseSample("Issue290");
-        CommentsCollection cc = (CommentsCollection) result.getCommentsCollection().get();
-        assertEquals(1, cc.getLineComments().size());
-        assertEquals(1, cc.getJavadocComments().size());
-    }
-
-    @Test
-    public void issue624() throws IOException {
-        parseResource(makeFilename("Issue624"));
-        // Should not fail
-    }
-
-    @Test
-    public void issue200EnumConstantsWithCommentsForceVerticalAlignment() {
-        CompilationUnit cu = parse("public enum X {" + EOL +
-                "    /** const1 javadoc */" + EOL +
-                "    BORDER_CONSTANT," + EOL +
-                "    /** const2 javadoc */" + EOL +
-                "    ANOTHER_CONSTANT" + EOL +
-                "}");
-        assertEqualsNoEol("public enum X {\n" +
-                "\n" +
-                "    /**\n" +
-                "     * const1 javadoc\n" +
-                "     */\n" +
-                "    BORDER_CONSTANT,\n" +
-                "    /**\n" +
-                "     * const2 javadoc\n" +
-                "     */\n" +
-                "    ANOTHER_CONSTANT\n" +
-                "}\n", cu.toString());
-    }
-
-    @Test
-    public void issue234LosingCommentsInArrayInitializerExpr() {
-        CompilationUnit cu = parse("@Anno(stuff={" + EOL +
-                "    // Just," + EOL +
-                "    // an," + EOL +
-                "    // example" + EOL +
-                "})" + EOL +
-                "class ABC {" + EOL +
-                "" + EOL +
-                "}");
-
-        assertEqualsNoEol("@Anno(stuff = {// Just,\n" +
-                "// an,\n" +
-                "// example\n" +
-                "})\n" +
-                "class ABC {\n" +
-                "}\n", cu.toString());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/GeneratedJavaParserTokenManagerTest.java b/javaparser-testing/src/test/java/com/github/javaparser/GeneratedJavaParserTokenManagerTest.java
deleted file mode 100644
index fdecede..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/GeneratedJavaParserTokenManagerTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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;
-
-import org.junit.Test;
-
-import java.io.IOException;
-
-public class GeneratedJavaParserTokenManagerTest {
-    private String makeFilename(String sampleName) {
-        return "com/github/javaparser/issue_samples/" + sampleName + ".java.txt";
-    }
-
-    @Test
-    public void issue1003() throws IOException {
-        JavaParser.parseResource(makeFilename("issue1003"));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/JavaParserTest.java b/javaparser-testing/src/test/java/com/github/javaparser/JavaParserTest.java
deleted file mode 100644
index 7302e95..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/JavaParserTest.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.ArrayCreationExpr;
-import com.github.javaparser.ast.expr.CastExpr;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.LambdaExpr;
-import com.github.javaparser.ast.stmt.*;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import com.github.javaparser.ast.type.IntersectionType;
-import com.github.javaparser.ast.type.Type;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.Range.range;
-import static com.github.javaparser.utils.CodeGenerationUtils.mavenModuleRoot;
-import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class JavaParserTest {
-
-    @Test
-    public void rangeOfAnnotationMemberDeclarationIsCorrect() {
-        String code = "@interface AD { String foo(); }";
-        CompilationUnit cu = JavaParser.parse(code);
-        AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
-        assertEquals(true, memberDeclaration.getRange().isPresent());
-        assertEquals(new Range(new Position(1, 17), new Position(1, 29)), memberDeclaration.getRange().get());
-    }
-
-    @Test
-    public void rangeOfAnnotationMemberDeclarationWithArrayTypeIsCorrect() {
-        String code = "@interface AD { String[] foo(); }";
-        CompilationUnit cu = JavaParser.parse(code);
-        AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
-        assertEquals(true, memberDeclaration.getRange().isPresent());
-        assertEquals(new Range(new Position(1, 17), new Position(1, 31)), memberDeclaration.getRange().get());
-    }
-
-    @Test
-    public void rangeOfArrayCreationLevelWithExpressionIsCorrect() {
-        String code = "new int[123][456]";
-        ArrayCreationExpr expression = JavaParser.parseExpression(code);
-        Optional<Range> range;
-
-        range = expression.getLevels().get(0).getRange();
-        assertEquals(true, range.isPresent());
-        assertEquals(new Range(new Position(1, 8), new Position(1, 12)), range.get());
-
-        range = expression.getLevels().get(1).getRange();
-        assertEquals(true, range.isPresent());
-        assertEquals(new Range(new Position(1, 13), new Position(1, 17)), range.get());
-    }
-
-    @Test
-    public void rangeOfArrayCreationLevelWithoutExpressionIsCorrect() {
-        String code = "new int[][]";
-        ArrayCreationExpr expression = JavaParser.parseExpression(code);
-        Optional<Range> range;
-
-        range = expression.getLevels().get(0).getRange();
-        assertEquals(true, range.isPresent());
-        assertEquals(new Range(new Position(1, 8), new Position(1, 9)), range.get());
-
-        range = expression.getLevels().get(1).getRange();
-        assertEquals(true, range.isPresent());
-        assertEquals(new Range(new Position(1, 10), new Position(1, 11)), range.get());
-    }
-
-    @Test
-    public void parseErrorContainsLocation() {
-        ParseResult<CompilationUnit> result = new JavaParser().parse(COMPILATION_UNIT, provider("class X { // blah"));
-
-        Problem problem = result.getProblem(0);
-        assertEquals(range(1, 9, 1, 17), problem.getLocation().get().toRange().get());
-        assertEquals("Parse error. Found <EOF>, expected one of  \";\" \"<\" \"@\" \"abstract\" \"boolean\" \"byte\" \"char\" \"class\" \"default\" \"double\" \"enum\" \"exports\" \"final\" \"float\" \"int\" \"interface\" \"long\" \"module\" \"native\" \"open\" \"opens\" \"private\" \"protected\" \"provides\" \"public\" \"requires\" \"short\" \"static\" \"strictfp\" \"synchronized\" \"to\" \"transient\" \"transitive\" \"uses\" \"void\" \"volatile\" \"with\" \"{\" \"}\" <IDENTIFIER>", problem.getMessage());
-        assertInstanceOf(ParseException.class, problem.getCause().get());
-    }
-
-    @Test
-    public void parseIntersectionType() {
-        String code = "(Runnable & Serializable) (() -> {})";
-        Expression expression = JavaParser.parseExpression(code);
-        Type type = expression.asCastExpr().getType();
-
-        assertTrue(type instanceof IntersectionType);
-        IntersectionType intersectionType = type.asIntersectionType();
-        assertEquals(2, intersectionType.getElements().size());
-        assertTrue(intersectionType.getElements().get(0) instanceof ClassOrInterfaceType);
-        assertEquals("Runnable", intersectionType.getElements().get(0).asClassOrInterfaceType().getNameAsString());
-        assertTrue(intersectionType.getElements().get(1) instanceof ClassOrInterfaceType);
-        assertEquals("Serializable", intersectionType.getElements().get(1).asClassOrInterfaceType().getNameAsString());
-    }
-
-    @Test
-    public void rangeOfIntersectionType() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
-        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
-        Type type = castExpr.getType();
-        assertEquals(range(3, 13, 3, 54), type.getRange().get());
-    }
-
-    @Test
-    public void rangeOfCast() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
-        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
-        assertEquals(range(3, 12, 3, 101), castExpr.getRange().get());
-    }
-
-    @Test
-    public void rangeOfCastNonIntersection() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>>               )(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
-        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
-        assertEquals(range(3, 12, 3, 101), castExpr.getRange().get());
-    }
-
-    @Test
-    public void rangeOfLambda() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
-        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
-        LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
-        assertEquals(range(3, 56, 3, 101), lambdaExpr.getRange().get());
-        assertEquals(GeneratedJavaParserConstants.LPAREN, lambdaExpr.getTokenRange().get().getBegin().getKind());
-        assertEquals(GeneratedJavaParserConstants.RPAREN, lambdaExpr.getTokenRange().get().getEnd().getKind());
-    }
-
-    @Test
-    public void rangeOfLambdaBody() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
-        CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
-        LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
-        Statement lambdaBody = lambdaExpr.getBody();
-        assertEquals(range(3, 68, 3, 101), lambdaBody.getRange().get());
-    }
-
-    @Test
-    public void testNotStoringTokens() {
-        JavaParser javaParser = new JavaParser(new ParserConfiguration().setStoreTokens(false));
-        ParseResult<CompilationUnit> result = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{}"));
-        assertEquals(false, result.getTokens().isPresent());
-    }
-
-    @Test(expected = ParseProblemException.class)
-    public void trailingCodeIsAnError() {
-        JavaParser.parseBlock("{} efijqoifjqefj");
-    }
-
-    @Test
-    public void trailingWhitespaceIsIgnored() {
-        BlockStmt blockStmt = JavaParser.parseBlock("{} // hello");
-        assertEquals("{}", blockStmt.getTokenRange().get().toString());
-    }
-
-    @Test
-    public void everyTokenHasACategory() throws IOException {
-        final int tokenCount = GeneratedJavaParserConstants.tokenImage.length;
-        Path tokenTypesPath = mavenModuleRoot(JavaParserTest.class).resolve("../javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java");
-        CompilationUnit tokenTypesCu = JavaParser.parse(tokenTypesPath);
-        // -1 to take off the default: case.
-        int switchEntries = tokenTypesCu.findAll(SwitchEntryStmt.class).size()-1;
-        // The amount of "case XXX:" in TokenTypes.java should be equal to the amount of tokens JavaCC knows about:
-        assertEquals(tokenCount, switchEntries);
-    }
-
-    @Test
-    public void parsingInitializedAndUnitializedVarsInForStmt() {
-        ForStmt forStmt = JavaParser.parseStatement("for(int a,b=0;;){}").asForStmt();
-        assertEquals(1, forStmt.getInitialization().size());
-        assertEquals(true, forStmt.getInitialization().get(0).isVariableDeclarationExpr());
-        assertEquals(2, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().size());
-        assertEquals("a", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getNameAsString());
-        assertEquals("b", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getNameAsString());
-        assertEquals(false, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getInitializer().isPresent());
-        assertEquals(true, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getInitializer().isPresent());
-    }
-
-    @Test
-    public void parsingInitializedAndUnitializedVarsInForStmtComplexCase() {
-        // See issue 1281
-        ForStmt forStmt = JavaParser.parseStatement("for(int i, j = array2.length - 1;;){}").asForStmt();
-        assertEquals(1, forStmt.getInitialization().size());
-        assertEquals(true, forStmt.getInitialization().get(0).isVariableDeclarationExpr());
-        assertEquals(2, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().size());
-        assertEquals("i", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getNameAsString());
-        assertEquals("j", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getNameAsString());
-        assertEquals(false, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getInitializer().isPresent());
-        assertEquals(true, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getInitializer().isPresent());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/JavaTokenTest.java b/javaparser-testing/src/test/java/com/github/javaparser/JavaTokenTest.java
deleted file mode 100644
index e69a76a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/JavaTokenTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.ast.expr.Expression;
-import org.junit.Test;
-
-import java.util.Iterator;
-
-import static com.github.javaparser.GeneratedJavaParserConstants.*;
-import static com.github.javaparser.JavaToken.Category.*;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.Range.range;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class JavaTokenTest {
-
-    @Test
-    public void testAFewTokens() {
-        ParseResult<Expression> result = new JavaParser().parse(ParseStart.EXPRESSION, provider("1 +/*2*/1 "));
-        Iterator<JavaToken> iterator = result.getResult().get().getTokenRange().get().iterator();
-        assertToken("1", range(1, 1, 1, 1), INTEGER_LITERAL, LITERAL, iterator.next());
-        assertToken(" ", range(1, 2, 1, 2), SPACE, WHITESPACE_NO_EOL, iterator.next());
-        assertToken("+", range(1, 3, 1, 3), PLUS, OPERATOR, iterator.next());
-        assertToken("/*2*/", range(1, 4, 1, 8), MULTI_LINE_COMMENT, COMMENT, iterator.next());
-        assertToken("1", range(1, 9, 1, 9), INTEGER_LITERAL, LITERAL, iterator.next());
-        assertToken(" ", range(1, 10, 1, 10), SPACE, WHITESPACE_NO_EOL, iterator.next());
-        assertToken("", range(1, 10, 1, 10), EOF, WHITESPACE_NO_EOL, iterator.next());
-        assertEquals(false, iterator.hasNext());
-    }
-
-    private void assertToken(String image, Range range, int kind, JavaToken.Category category, JavaToken token) {
-        assertEquals(image, token.getText());
-        assertEquals(range, token.getRange().get());
-        assertEquals(kind, token.getKind());
-        assertEquals(category, token.getCategory());
-        token.getNextToken().ifPresent(nt -> assertEquals(token, nt.getPreviousToken().get()));
-        token.getPreviousToken().ifPresent(pt -> assertEquals(token, pt.getNextToken().get()));
-        assertTrue(token.getNextToken().isPresent() || token.getPreviousToken().isPresent());
-    }
-
-    @Test
-    public void testAFewImagesForTokenKinds() {
-        assertEquals("=", new JavaToken(ASSIGN).getText());
-        // TODO this shouldn't be a space.
-        assertEquals(" ", new JavaToken(EOF).getText());
-        assertEquals("*/", new JavaToken(JAVADOC_COMMENT).getText());
-    }
-
-    @Test
-    public void testKindEnum() {
-        JavaToken.Kind kind = JavaToken.Kind.valueOf(GeneratedJavaParserConstants.ASSERT);
-
-        assertEquals(JavaToken.Kind.ASSERT, kind);
-        assertEquals(GeneratedJavaParserConstants.ASSERT, kind.getKind());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/JavadocParserTest.java b/javaparser-testing/src/test/java/com/github/javaparser/JavadocParserTest.java
deleted file mode 100644
index 99e138e..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/JavadocParserTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.javadoc.Javadoc;
-import com.github.javaparser.javadoc.JavadocBlockTag;
-import com.github.javaparser.javadoc.description.JavadocDescription;
-import org.junit.Assert;
-import org.junit.Test;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class JavadocParserTest {
-
-    @Test
-    public void parseSimplestContent() {
-        Assert.assertEquals(new Javadoc(JavadocDescription.parseText("A simple line of text")),
-                JavadocParser.parse("A simple line of text"));
-    }
-
-    @Test
-    public void parseSingleLineWithSpacing() {
-        assertEquals(new Javadoc(JavadocDescription.parseText("The line number of the first character of this Token.")),
-                JavadocParser.parse(" The line number of the first character of this Token. "));
-    }
-
-    @Test
-    public void parseSingleLineWithNewLines() {
-        assertEquals(new Javadoc(JavadocDescription.parseText("The string image of the token.")),
-                JavadocParser.parse(EOL +
-                        "   * The string image of the token." + EOL +
-                        "   "));
-    }
-
-    @Test
-    public void parseCommentWithNewLines() {
-        String text = EOL +
-                "   * The version identifier for this Serializable class." + EOL +
-                "   * Increment only if the <i>serialized</i> form of the" + EOL +
-                "   * class changes." + EOL +
-                "   ";
-        assertEquals(new Javadoc(JavadocDescription.parseText("The version identifier for this Serializable class." + EOL +
-                        "Increment only if the <i>serialized</i> form of the" + EOL +
-                        "class changes.")),
-                JavadocParser.parse(text));
-    }
-
-    @Test
-    public void parseCommentWithIndentation() {
-        String text = "Returns a new Token object, by default." + EOL +
-                "   * However, if you want, you can create and return subclass objects based on the value of ofKind." + EOL +
-                "   *" + EOL +
-                "   *    case MyParserConstants.ID : return new IDToken(ofKind, image);" + EOL +
-                "   *" + EOL +
-                "   * to the following switch statement. Then you can cast matchedToken";
-        assertEquals(new Javadoc(JavadocDescription.parseText("Returns a new Token object, by default." + EOL +
-                        "However, if you want, you can create and return subclass objects based on the value of ofKind." + EOL +
-                        EOL +
-                        "   case MyParserConstants.ID : return new IDToken(ofKind, image);" + EOL +
-                        EOL +
-                        "to the following switch statement. Then you can cast matchedToken")),
-                JavadocParser.parse(text));
-    }
-
-    @Test
-    public void parseBlockTagsAndEmptyDescription() {
-        String text = EOL +
-                "   * @deprecated" + EOL +
-                "   * @see #getEndColumn" + EOL +
-                "   ";
-        assertEquals(new Javadoc(JavadocDescription.parseText(""))
-                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.DEPRECATED, ""))
-                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.SEE, "#getEndColumn")), JavadocParser.parse(text));
-    }
-
-    @Test
-    public void parseBlockTagsAndProvideTagName() {
-        String expectedText = EOL +
-                "   * @unofficial" + EOL + " " +
-                "   ";
-
-        Javadoc underTest = new Javadoc(JavadocDescription.parseText(""))
-                .addBlockTag(new JavadocBlockTag("unofficial", ""));
-
-
-        assertEquals(underTest, JavadocParser.parse(expectedText));
-        assertEquals(1, underTest.getBlockTags().size());
-        assertEquals("unofficial", underTest.getBlockTags().get(0).getTagName());
-    }
-
-    @Test
-    public void parseParamBlockTags() {
-        String text = EOL +
-                "     * Add a field to this and automatically add the import of the type if needed" + EOL +
-                "     *" + EOL +
-                "     * @param typeClass the type of the field" + EOL +
-                "     * @param name the name of the field" + EOL +
-                "     * @param modifiers the modifiers like {@link Modifier#PUBLIC}" + EOL +
-                "     * @return the {@link FieldDeclaration} created" + EOL +
-                "     ";
-        Javadoc res = JavadocParser.parse(text);
-        assertEquals(new Javadoc(JavadocDescription.parseText("Add a field to this and automatically add the import of the type if needed"))
-                .addBlockTag(JavadocBlockTag.createParamBlockTag("typeClass", "the type of the field"))
-                .addBlockTag(JavadocBlockTag.createParamBlockTag("name", "the name of the field"))
-                .addBlockTag(JavadocBlockTag.createParamBlockTag("modifiers", "the modifiers like {@link Modifier#PUBLIC}"))
-                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.RETURN, "the {@link FieldDeclaration} created")), res);
-    }
-
-    @Test
-    public void parseMultilineParamBlockTags() {
-        String text = EOL +
-                "     * Add a field to this and automatically add the import of the type if needed" + EOL +
-                "     *" + EOL +
-                "     * @param typeClass the type of the field" + EOL +
-                "     *     continued in a second line" + EOL +
-                "     * @param name the name of the field" + EOL +
-                "     * @param modifiers the modifiers like {@link Modifier#PUBLIC}" + EOL +
-                "     * @return the {@link FieldDeclaration} created" + EOL +
-                "     ";
-        Javadoc res = JavadocParser.parse(text);
-        assertEquals(new Javadoc(JavadocDescription.parseText("Add a field to this and automatically add the import of the type if needed"))
-                .addBlockTag(JavadocBlockTag.createParamBlockTag("typeClass", "the type of the field" + EOL + "    continued in a second line"))
-                .addBlockTag(JavadocBlockTag.createParamBlockTag("name", "the name of the field"))
-                .addBlockTag(JavadocBlockTag.createParamBlockTag("modifiers", "the modifiers like {@link Modifier#PUBLIC}"))
-                .addBlockTag(new JavadocBlockTag(JavadocBlockTag.Type.RETURN, "the {@link FieldDeclaration} created")), res);
-    }
-
-    @Test
-    public void startsWithAsteriskEmpty() {
-        assertEquals(-1, JavadocParser.startsWithAsterisk(""));
-    }
-
-    @Test
-    public void startsWithAsteriskNoAsterisk() {
-        assertEquals(-1, JavadocParser.startsWithAsterisk(" ciao"));
-    }
-
-    @Test
-    public void startsWithAsteriskAtTheBeginning() {
-        assertEquals(0, JavadocParser.startsWithAsterisk("* ciao"));
-    }
-
-    @Test
-    public void startsWithAsteriskAfterSpaces() {
-        assertEquals(3, JavadocParser.startsWithAsterisk("   * ciao"));
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ParseErrorRecoveryTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ParseErrorRecoveryTest.java
deleted file mode 100644
index b41c28b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ParseErrorRecoveryTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.github.javaparser;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.stmt.LabeledStmt;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
-import static org.junit.Assert.assertEquals;
-
-public class ParseErrorRecoveryTest {
-    private final JavaParser parser = new JavaParser();
-
-    @Test
-    public void compilationUnitRecovery() {
-        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, provider("XXX")).getResult().get();
-        assertEquals(UNPARSABLE, cu.getParsed());
-    }
-
-    @Test
-    public void bodystatementSemicolonRecovery() {
-        MethodDeclaration cu = parser.parse(ParseStart.CLASS_BODY, provider("int x(){X X X;}")).getResult().get().asMethodDeclaration();
-        Statement xxx = cu.getBody().get().getStatements().get(0);
-        assertEquals(UNPARSABLE, xxx.getParsed());
-    }
-
-    @Test
-    public void bodystatementClosingBraceRecovery() {
-        MethodDeclaration cu = parser.parse(ParseStart.CLASS_BODY, provider("int x(){X X X}")).getResult().get().asMethodDeclaration();
-        Statement xxx = cu.getBody().get();
-        assertEquals(UNPARSABLE, xxx.getParsed());
-    }
-
-    @Test
-    public void labeledStatementSemicolonRecovery() {
-        CompilationUnit cu = parser.parse(ParseStart.COMPILATION_UNIT, provider("class X{int x(){aaa:X X X;}}")).getResult().get();
-        LabeledStmt xxx = cu.getClassByName("X").get().getMethods().get(0).getBody().get().getStatements().get(0).asLabeledStmt();
-        assertEquals(UNPARSABLE, xxx.getStatement().getParsed());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java
deleted file mode 100644
index abc4009..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ParserConfigurationTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.github.javaparser;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.stmt.Statement;
-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;
-
-public class ParserConfigurationTest {
-    @Test
-    public void storeNoTokens() {
-        ParseResult<CompilationUnit> result = new JavaParser(new ParserConfiguration().setStoreTokens(false)).parse(ParseStart.COMPILATION_UNIT, provider("class X{}"));
-
-        assertFalse(result.getResult().get().getTokenRange().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(RAW))
-                        .parse(STATEMENT, provider("try{}"));
-        assertEquals(true, result.isSuccessful());
-    }
-
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ProblemTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ProblemTest.java
deleted file mode 100644
index 0654344..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ProblemTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.github.javaparser;
-
-import org.junit.Test;
-
-import static com.github.javaparser.Range.range;
-import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
-import static org.junit.Assert.assertEquals;
-
-public class ProblemTest {
-    @Test
-    public void testSimpleGetters() {
-        Problem problem = new Problem("Parse error", TokenRange.INVALID, new Exception());
-
-        assertEquals(TokenRange.INVALID, problem.getLocation().get());
-        assertEquals("Parse error", problem.getMessage());
-        assertInstanceOf(Exception.class, problem.getCause().get());
-    }
-
-    @Test
-    public void testVerboseMessage() {
-        Problem problem = new Problem("Parse error", TokenRange.INVALID, null);
-
-        assertEquals("(line ?,col ?) Parse error", problem.getVerboseMessage());
-    }
-
-    @Test
-    public void testVerboseMessageWithoutLocation() {
-        Problem problem = new Problem("Parse error", null, null);
-
-        assertEquals("Parse error", problem.getVerboseMessage());
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ProvidersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ProvidersTest.java
deleted file mode 100644
index 14b351a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ProvidersTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-
-import static org.junit.Assert.*;
-
-public class ProvidersTest {
-
-    @Test
-    public void testResourceProvider() throws IOException {
-        Provider provider = Providers.resourceProvider("com/github/javaparser/issue_samples/Issue290.java.txt");
-        assertNotNull(provider);
-        JavaParser parser = new JavaParser();
-        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
-        assertTrue(parse.isSuccessful());
-    }
-
-    @Test
-    public void testResourceProviderWithWrongEncoding() throws IOException {
-        Provider provider = Providers.resourceProvider("com/github/javaparser/TestFileIso88591.java");
-        assertNotNull(provider);
-        JavaParser parser = new JavaParser();
-        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
-        assertFalse(parse.isSuccessful());
-    }
-
-    @Test
-    public void testResourceProviderWithEncoding() throws IOException {
-        Provider provider = Providers.resourceProvider(
-                "com/github/javaparser/TestFileIso88591.java",
-                Charset.forName("ISO-8859-1")
-        );
-        assertNotNull(provider);
-        JavaParser parser = new JavaParser();
-        ParseResult<CompilationUnit> parse = parser.parse(ParseStart.COMPILATION_UNIT, provider);
-        assertTrue(parse.isSuccessful());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/RangeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/RangeTest.java
deleted file mode 100644
index 1d2b49a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/RangeTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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;
-
-import org.junit.Test;
-
-import java.io.IOException;
-
-import static org.junit.Assert.assertEquals;
-
-public class RangeTest {
-
-    @Test
-    public void aRangeContainsItself() throws IOException {
-        Range r = Range.range(1, 1, 3, 10);
-        assertEquals(true, r.contains(r));
-    }
-
-    @Test
-    public void aRangeDoesNotStrictlyContainsItself() throws IOException {
-        Range r = Range.range(1, 1, 3, 10);
-        assertEquals(false, r.strictlyContains(r));
-    }
-
-    @Test
-    public void overlappingButNotContainedRangesAreNotOnContains() throws IOException {
-        Range r1 = Range.range(1, 1, 3, 10);
-        Range r2 = Range.range(2, 1, 7, 10);
-        assertEquals(false, r1.contains(r2));
-        assertEquals(false, r2.contains(r1));
-    }
-
-    @Test
-    public void overlappingButNotContainedRangesAreNotOnStrictlyContains() throws IOException {
-        Range r1 = Range.range(1, 1, 3, 10);
-        Range r2 = Range.range(2, 1, 7, 10);
-        assertEquals(false, r1.strictlyContains(r2));
-        assertEquals(false, r2.strictlyContains(r1));
-    }
-
-    @Test
-    public void unrelatedRangesAreNotOnContains() throws IOException {
-        Range r1 = Range.range(1, 1, 3, 10);
-        Range r2 = Range.range(5, 1, 7, 10);
-        assertEquals(false, r1.contains(r2));
-        assertEquals(false, r2.contains(r1));
-    }
-
-    @Test
-    public void unrelatedRangesAreNotOnStrictlyContains() throws IOException {
-        Range r1 = Range.range(1, 1, 3, 10);
-        Range r2 = Range.range(5, 1, 7, 10);
-        assertEquals(false, r1.strictlyContains(r2));
-        assertEquals(false, r2.strictlyContains(r1));
-    }
-
-    @Test
-    public void strictlyContainedRangesOnContains() throws IOException {
-        Range r1 = Range.range(1, 1, 3, 10);
-        Range r2 = Range.range(2, 1, 3, 4);
-        assertEquals(true, r1.contains(r2));
-        assertEquals(false, r2.contains(r1));
-    }
-
-    @Test
-    public void strictlyContainedRangesOnStrictlyContains() throws IOException {
-        Range r1 = Range.range(1, 1, 3, 10);
-        Range r2 = Range.range(2, 1, 3, 4);
-        assertEquals(true, r1.strictlyContains(r2));
-        assertEquals(false, r2.strictlyContains(r1));
-    }
-
-    @Test
-    public void containsConsiderLines() {
-        Range r1 = Range.range(22, 9, 22, 29);
-        Range r2 = Range.range(26, 19, 26, 28);
-        assertEquals(false, r1.contains(r2));
-        assertEquals(false, r2.contains(r1));
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/TokenRangeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/TokenRangeTest.java
deleted file mode 100644
index d067c8e..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/TokenRangeTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.github.javaparser;
-
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class TokenRangeTest {
-    @Test
-    public void toStringWorks() {
-        CompilationUnit cu = JavaParser.parse("class X {\n\tX(){\n// hello\n}\n}");
-        assertEquals("X(){\n// hello\n}", cu.getClassByName("X").get().getDefaultConstructor().get().getTokenRange().get().toString());
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/CompilationUnitTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/CompilationUnitTest.java
deleted file mode 100644
index ec17e39..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/CompilationUnitTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.JavaParser;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import static com.github.javaparser.JavaParser.parse;
-import static com.github.javaparser.utils.CodeGenerationUtils.mavenModuleRoot;
-import static org.junit.Assert.assertEquals;
-
-public class CompilationUnitTest {
-    @Test
-    public void issue578TheFirstCommentIsWithinTheCompilationUnit() {
-        CompilationUnit compilationUnit = parse("// This is my class, with my comment\n" +
-                "class A {\n" +
-                "    static int a;\n" +
-                "}");
-
-        assertEquals(1, compilationUnit.getAllContainedComments().size());
-    }
-
-    @Test
-    public void testGetSourceRoot() throws IOException {
-        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
-        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "Z.java"));
-
-        CompilationUnit cu = parse(testFile);
-        Path sourceRoot1 = cu.getStorage().get().getSourceRoot();
-        assertEquals(sourceRoot, sourceRoot1);
-    }
-
-    @Test(expected = RuntimeException.class)
-    public void testGetSourceRootWithBadPackageDeclaration() throws IOException {
-        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
-        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "A.java"));
-
-        CompilationUnit cu = parse(testFile);
-        cu.getStorage().get().getSourceRoot();
-    }
-
-    @Test
-    public void testGetSourceRootInDefaultPackage() throws IOException {
-        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources", "com", "github", "javaparser", "storage")).normalize();
-        Path testFile = sourceRoot.resolve(Paths.get("B.java"));
-
-        CompilationUnit cu = parse(testFile);
-        Path sourceRoot1 = cu.getStorage().get().getSourceRoot();
-        assertEquals(sourceRoot, sourceRoot1);
-    }
-    
-    @Test
-    public void testGetPrimaryTypeName() throws IOException {
-        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
-        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "PrimaryType.java"));
-        CompilationUnit cu = JavaParser.parse(testFile);
-        
-        assertEquals("PrimaryType", cu.getPrimaryTypeName().get());
-    }
-
-    @Test
-    public void testNoPrimaryTypeName() {
-        CompilationUnit cu = JavaParser.parse("class PrimaryType{}");
-
-        assertEquals(false, cu.getPrimaryTypeName().isPresent());
-    }
-    @Test
-    public void testGetPrimaryType() throws IOException {
-        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
-        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "PrimaryType.java"));
-        CompilationUnit cu = JavaParser.parse(testFile);
-
-        assertEquals("PrimaryType",     cu.getPrimaryType().get().getNameAsString());
-    }
-
-    @Test
-    public void testNoPrimaryType() throws IOException {
-        Path sourceRoot = mavenModuleRoot(CompilationUnitTest.class).resolve(Paths.get("src", "test", "resources")).normalize();
-        Path testFile = sourceRoot.resolve(Paths.get("com", "github", "javaparser", "storage", "PrimaryType2.java"));
-        CompilationUnit cu = JavaParser.parse(testFile);
-
-        assertEquals(false, cu.getPrimaryType().isPresent());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/DataKeyTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/DataKeyTest.java
deleted file mode 100644
index 9116365..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/DataKeyTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.ast.expr.SimpleName;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
-
-public class DataKeyTest {
-    public static final DataKey<String> ABC = new DataKey<String>() {
-    };
-    public static final DataKey<List<String>> LISTY = new DataKey<List<String>>() {
-    };
-    public static final DataKey<List<String>> DING = new DataKey<List<String>>() {
-    };
-
-    @Test
-    public void addAFewKeysAndSeeIfTheyAreStoredCorrectly() {
-        Node node = new SimpleName();
-
-        node.setData(ABC, "Hurray!");
-        node.setData(LISTY, Arrays.asList("a", "b"));
-        node.setData(ABC, "w00t");
-
-        assertThat(node.getData(ABC)).contains("w00t");
-        assertThat(node.getData(LISTY)).containsExactly("a", "b");
-        assertThat(node.getData(DING)).isNull();
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/NodeListTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/NodeListTest.java
deleted file mode 100644
index 8e4d568..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/NodeListTest.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.expr.SimpleName;
-import com.github.javaparser.ast.observer.AstObserver;
-import com.github.javaparser.ast.observer.ObservableProperty;
-import com.github.javaparser.ast.type.PrimitiveType;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.LinkedList;
-import java.util.List;
-
-import static com.github.javaparser.ast.NodeList.nodeList;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class NodeListTest {
-
-    private AstObserver createObserver(List<String> changes) {
-        return new AstObserver() {
-            @Override
-            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add(String.format("change of property %s for %s: from '%s' to '%s'", property, observedNode, oldValue, newValue));
-            }
-
-            @Override
-            public void parentChange(Node observedNode, Node previousParent, Node newParent) {
-                changes.add(String.format("setting parent for %s: was %s, now is %s", observedNode, previousParent, newParent));
-            }
-
-            @Override
-            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
-                changes.add(String.format("'%s' %s in list at %d", nodeAddedOrRemoved, type, index));
-            }
-
-            @Override
-            public void listReplacement(NodeList observedNode, int index, Node oldNode, Node newNode) {
-                changes.add(String.format("'%s' %s in list at %d", oldNode, ListChangeType.REMOVAL, index));
-                changes.add(String.format("'%s' %s in list at %d", newNode, ListChangeType.ADDITION, index));
-            }
-        };
-    }
-
-    private FieldDeclaration createIntField(String name) {
-        return new FieldDeclaration(EnumSet.noneOf(Modifier.class), PrimitiveType.intType(), name);
-    }
-
-    @Test
-    public void addAllWithoutIndex() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { void foo(int p) { }}";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().addAll(Arrays.asList(createIntField("a"), createIntField("b"), createIntField("c")));
-        assertEquals(Arrays.asList("'int a;' ADDITION in list at 1",
-                "'int b;' ADDITION in list at 2",
-                "'int c;' ADDITION in list at 3"), changes);
-    }
-
-    @Test
-    public void addAllWithIndex() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { void foo(int p) { }}";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().addAll(0, Arrays.asList(createIntField("a"), createIntField("b"), createIntField("c")));
-        assertEquals(Arrays.asList("'int a;' ADDITION in list at 0",
-                "'int b;' ADDITION in list at 1",
-                "'int c;' ADDITION in list at 2"), changes);
-    }
-
-    @Test
-    public void clear() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().clear();
-        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0",
-                "'int b;' REMOVAL in list at 0",
-                "'int c;' REMOVAL in list at 0"), changes);
-    }
-
-    @Test
-    public void set() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().set(1, createIntField("d"));
-        assertEquals(Arrays.asList("'int b;' REMOVAL in list at 1",
-                "'int d;' ADDITION in list at 1"), changes);
-    }
-
-    @Test
-    public void removeNode() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; int d; int e; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().remove(cd.getFieldByName("c").get());
-        assertEquals(Arrays.asList("'int c;' REMOVAL in list at 2"), changes);
-    }
-
-    @Test
-    public void removeFirstNode() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; int d; int e; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().removeFirst();
-        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0"), changes);
-        assertEquals(cd.getMembers().size(), 4);
-
-        for (int i = 3; i >= 0; i--) {
-            assertTrue(cd.getMembers().removeFirst() != null);
-            assertEquals(cd.getMembers().size(), i);
-        }
-
-        assertEquals(cd.getMembers().size(), 0);
-    }
-
-    @Test
-    public void removeLastNode() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; int d; int e; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().removeLast();
-        assertEquals(Arrays.asList("'int e;' REMOVAL in list at 4"), changes);
-        assertEquals(cd.getMembers().size(), 4);
-
-        for (int i = 3; i >= 0; i--) {
-            assertTrue(cd.getMembers().removeLast() != null);
-            assertEquals(cd.getMembers().size(), i);
-        }
-
-        assertEquals(cd.getMembers().size(), 0);
-    }
-
-    @Test
-    public void removeObject() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; int d; int e; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().remove("hi");
-        assertEquals(Arrays.asList(), changes);
-    }
-
-    @Test
-    public void removeAll() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; int d; int e; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().removeAll(Arrays.asList(cd.getFieldByName("b").get(), "foo", cd.getFieldByName("d").get()));
-        assertEquals(Arrays.asList("'int b;' REMOVAL in list at 1",
-                "'int d;' REMOVAL in list at 2"), changes);
-    }
-
-    @Test
-    public void retainAll() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; int d; int e; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().retainAll(Arrays.asList(cd.getFieldByName("b").get(), "foo", cd.getFieldByName("d").get()));
-        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0",
-                "'int c;' REMOVAL in list at 1",
-                "'int e;' REMOVAL in list at 2"), changes);
-    }
-
-    @Test
-    public void replaceAll() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int b; int c; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().replaceAll(bodyDeclaration -> {
-            FieldDeclaration clone = (FieldDeclaration) bodyDeclaration.clone();
-            SimpleName id = clone.getVariable(0).getName();
-            id.setIdentifier(id.getIdentifier().toUpperCase());
-            return clone;
-        });
-        assertEquals(Arrays.asList("'int a;' REMOVAL in list at 0", "'int A;' ADDITION in list at 0",
-                "'int b;' REMOVAL in list at 1", "'int B;' ADDITION in list at 1",
-                "'int c;' REMOVAL in list at 2", "'int C;' ADDITION in list at 2"), changes);
-    }
-
-    @Test
-    public void removeIf() {
-        List<String> changes = new LinkedList<>();
-        String code = "class A { int a; int longName; int c; }";
-        CompilationUnit cu = JavaParser.parse(code);
-        ClassOrInterfaceDeclaration cd = cu.getClassByName("A").get();
-        cd.getMembers().register(createObserver(changes));
-
-        cd.getMembers().removeIf(m -> ((FieldDeclaration) m).getVariable(0).getName().getIdentifier().length() > 3);
-        assertEquals(Arrays.asList("'int longName;' REMOVAL in list at 1"), changes);
-    }
-
-    @Test
-    public void replace() {
-        final NodeList<Name> list = nodeList(new Name("a"), new Name("b"), new Name("c"));
-
-        final boolean replaced = list.replace(new Name("b"), new Name("z"));
-
-        assertEquals(true, replaced);
-        assertEquals(3, list.size());
-        assertEquals("a", list.get(0).asString());
-        assertEquals("z", list.get(1).asString());
-        assertEquals("c", list.get(2).asString());
-    }
-
-    @Test
-    public void toStringTest() {
-        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), new Name("cde"));
-
-        assertEquals("[abc, bcd, cde]", list.toString());
-    }
-
-    @Test
-    public void addFirst() {
-        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), new Name("cde"));
-
-        list.addFirst(new Name("xxx"));
-
-        assertEquals("[xxx, abc, bcd, cde]", list.toString());
-    }
-
-    @Test
-    public void addLast() {
-        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), new Name("cde"));
-
-        list.addLast(new Name("xxx"));
-
-        assertEquals("[abc, bcd, cde, xxx]", list.toString());
-    }
-
-    @Test
-    public void addBefore() {
-        Name n = new Name("bcd");
-        final NodeList<Name> list = nodeList(new Name("abc"), n, new Name("cde"));
-
-        list.addBefore(new Name("xxx"), n);
-
-        assertEquals("[abc, xxx, bcd, cde]", list.toString());
-    }
-
-    @Test
-    public void addAfter() {
-        Name n = new Name("bcd");
-        final NodeList<Name> list = nodeList(new Name("abc"), n, new Name("cde"));
-
-        list.addAfter(new Name("xxx"), n);
-
-        assertEquals("[abc, bcd, xxx, cde]", list.toString());
-    }
-
-    @Test
-    public void addBeforeFirst() {
-        Name abc = new Name("abc");
-        final NodeList<Name> list = nodeList(abc, new Name("bcd"), new Name("cde"));
-
-        list.addBefore(new Name("xxx"), abc);
-
-        assertEquals("[xxx, abc, bcd, cde]", list.toString());
-    }
-
-    @Test
-    public void addAfterLast() {
-        Name cde = new Name("cde");
-        final NodeList<Name> list = nodeList(new Name("abc"), new Name("bcd"), cde);
-
-        list.addAfter(new Name("xxx"), cde);
-
-        assertEquals("[abc, bcd, cde, xxx]", list.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/NodePositionTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/NodePositionTest.java
deleted file mode 100644
index 5ce116d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/NodePositionTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.*;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class NodePositionTest {
-
-    private List<Node> getAllNodes(Node node) {
-        List<Node> nodes = new LinkedList<>();
-        nodes.add(node);
-        node.getChildNodes().forEach(c -> nodes.addAll(getAllNodes(c)));
-        return nodes;
-    }
-
-    @Test
-    public void packageProtectedClassShouldHavePositionSet() throws IOException {
-        ensureAllNodesHaveValidBeginPosition("class A { }");
-    }
-
-    @Test
-    public void packageProtectedInterfaceShouldHavePositionSet() throws IOException {
-        ensureAllNodesHaveValidBeginPosition("interface A { }");
-    }
-
-    @Test
-    public void packageProtectedEnumShouldHavePositionSet() throws IOException {
-        ensureAllNodesHaveValidBeginPosition("enum A { }");
-    }
-
-    @Test
-    public void packageProtectedAnnotationShouldHavePositionSet() throws IOException {
-        ensureAllNodesHaveValidBeginPosition("@interface A { }");
-    }
-
-    @Test
-    public void packageProtectedFieldShouldHavePositionSet() throws IOException {
-        ensureAllNodesHaveValidBeginPosition("public class A { int i; }");
-    }
-
-    @Test
-    public void packageProtectedMethodShouldHavePositionSet() throws IOException {
-      ensureAllNodesHaveValidBeginPosition("public class A { void foo() {} }");
-    }
-
-    @Test
-    public void packageProtectedConstructorShouldHavePositionSet() throws IOException {
-      ensureAllNodesHaveValidBeginPosition("public class A { A() {} }");
-    }
-
-    private void ensureAllNodesHaveValidBeginPosition(final String code) throws IOException {
-        ParseResult<CompilationUnit> res = new JavaParser().parse(ParseStart.COMPILATION_UNIT, Providers.provider(code));
-        assertTrue(res.getProblems().isEmpty());
-
-        CompilationUnit cu = res.getResult().get();
-        getAllNodes(cu).forEach(n -> {
-            assertNotNull(String.format("There should be no node without a range: %s (class: %s)",
-                    n, n.getClass().getCanonicalName()), n.getRange());
-            if (n.getBegin().get().line == 0 && !n.toString().isEmpty()) {
-                throw new IllegalArgumentException("There should be no node at line 0: " + n + " (class: "
-                        + n.getClass().getCanonicalName() + ")");
-            }
-        });
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/NodeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/NodeTest.java
deleted file mode 100644
index 3201b29..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/NodeTest.java
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.VariableDeclarator;
-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.Expression;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.expr.SimpleName;
-import com.github.javaparser.ast.observer.AstObserver;
-import com.github.javaparser.ast.observer.AstObserverAdapter;
-import com.github.javaparser.ast.observer.ObservableProperty;
-import com.github.javaparser.ast.type.PrimitiveType;
-import org.junit.Test;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static com.github.javaparser.JavaParser.parse;
-import static com.github.javaparser.JavaParser.parseExpression;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.*;
-
-public class NodeTest {
-
-    @Test
-    public void registerSubTree() {
-        String code = "class A { int f; void foo(int p) { return 'z'; }}";
-        CompilationUnit cu = parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new AstObserverAdapter() {
-            @Override
-            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
-            }
-        };
-        cu.registerForSubtree(observer);
-
-        assertEquals(Arrays.asList(), changes);
-
-        cu.getClassByName("A").get().setName("MyCoolClass");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean",
-                "Parameter.name changed from p to myParam"), changes);
-    }
-
-    @Test
-    public void registerWithJustNodeMode() {
-        String code = "class A { int f; void foo(int p) { return 'z'; }}";
-        CompilationUnit cu = parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new AstObserverAdapter() {
-            @Override
-            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
-            }
-        };
-        cu.getClassByName("A").get().register(observer, Node.ObserverRegistrationMode.JUST_THIS_NODE);
-
-        assertEquals(Arrays.asList(), changes);
-
-        cu.getClassByName("A").get().setName("MyCoolClass");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
-
-        cu.getClassByName("MyCoolClass").get().addField("int", "bar").getVariables().get(0).setInitializer("0");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
-    }
-
-    @Test
-    public void registerWithNodeAndExistingDescendantsMode() {
-        String code = "class A { int f; void foo(int p) { return 'z'; }}";
-        CompilationUnit cu = parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new AstObserverAdapter() {
-            @Override
-            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
-            }
-        };
-        cu.getClassByName("A").get().register(observer, Node.ObserverRegistrationMode.THIS_NODE_AND_EXISTING_DESCENDANTS);
-
-        assertEquals(Arrays.asList(), changes);
-
-        cu.getClassByName("A").get().setName("MyCoolClass");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean",
-                "Parameter.name changed from p to myParam"), changes);
-
-        cu.getClassByName("MyCoolClass").get().addField("int", "bar").getVariables().get(0).setInitializer("0");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean",
-                "Parameter.name changed from p to myParam"), changes);
-    }
-
-    @Test
-    public void registerWithSelfPropagatingMode() {
-        String code = "class A { int f; void foo(int p) { return 'z'; }}";
-        CompilationUnit cu = parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new AstObserverAdapter() {
-            @Override
-            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
-            }
-        };
-        cu.getClassByName("A").get().register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
-
-        assertEquals(Arrays.asList(), changes);
-
-        cu.getClassByName("A").get().setName("MyCoolClass");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getFieldByName("f").get().getVariable(0).setType(new PrimitiveType(PrimitiveType.Primitive.BOOLEAN));
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean"), changes);
-
-        cu.getClassByName("MyCoolClass").get().getMethodsByName("foo").get(0).getParameterByName("p").get().setName("myParam");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean",
-                "Parameter.name changed from p to myParam"), changes);
-
-        cu.getClassByName("MyCoolClass").get()
-                .addField("int", "bar")
-                .getVariables().get(0).setInitializer("0");
-        assertEquals(Arrays.asList("ClassOrInterfaceDeclaration.name changed from A to MyCoolClass",
-                "FieldDeclaration.maximum_common_type changed from int to boolean",
-                "VariableDeclarator.type changed from int to boolean",
-                "Parameter.name changed from p to myParam",
-                "VariableDeclarator.initializer changed from null to 0"), changes);
-    }
-
-    @Test
-    public void deleteAParameterTriggerNotifications() {
-        String code = "class A { void foo(int p) { }}";
-        CompilationUnit cu = parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new AstObserverAdapter() {
-
-            @Override
-            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
-                changes.add("removing [" + nodeAddedOrRemoved + "] from index " + index);
-            }
-        };
-        cu.register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
-
-        cu.getClassByName("A").get().getMethodsByName("foo").get(0).getParameter(0).remove();
-        assertEquals(Arrays.asList("removing [int p] from index 0"), changes);
-    }
-
-    @Test
-    public void deleteClassNameDoesNotTriggerNotifications() {
-        String code = "class A { void foo(int p) { }}";
-        CompilationUnit cu = parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new AstObserverAdapter() {
-
-            @Override
-            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
-                changes.add("removing [" + nodeAddedOrRemoved + "] from index " + index);
-            }
-        };
-        cu.register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
-
-        // I cannot remove the name of a type
-        assertEquals(false, cu.getClassByName("A").get().getName().remove());
-        assertEquals(Arrays.asList(), changes);
-    }
-
-    @Test
-    public void deleteMethodBodyDoesTriggerNotifications() {
-        String code = "class A { void foo(int p) { }}";
-        CompilationUnit cu = parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new AstObserverAdapter() {
-
-            @Override
-            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add("setting [" + property + "] to " + newValue);
-            }
-
-            @Override
-            public void listChange(NodeList observedNode, ListChangeType type, int index, Node nodeAddedOrRemoved) {
-                changes.add("removing [" + nodeAddedOrRemoved + "] from index " + index);
-            }
-        };
-        cu.register(observer, Node.ObserverRegistrationMode.SELF_PROPAGATING);
-
-        assertEquals(true, cu.getClassByName("A").get().getMethodsByName("foo").get(0).getBody().get().remove());
-        assertEquals(Arrays.asList("setting [BODY] to null"), changes);
-    }
-
-    @Test
-    public void removeOrphanCommentPositiveCase() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class), false, "A");
-        Comment c = new LineComment("A comment");
-        decl.addOrphanComment(c);
-        assertEquals(1, decl.getOrphanComments().size());
-        assertTrue(decl == c.getParentNode().get());
-        assertTrue(decl.removeOrphanComment(c));
-        assertEquals(0, decl.getOrphanComments().size());
-        assertFalse(c.getParentNode().isPresent());
-    }
-
-    @Test
-    public void removeOrphanCommentNegativeCase() {
-        ClassOrInterfaceDeclaration aClass = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class), false, "A");
-        FieldDeclaration aField = new FieldDeclaration(EnumSet.noneOf(Modifier.class), new VariableDeclarator(PrimitiveType.intType(), "f"));
-        aClass.getMembers().add(aField);
-        Comment c = new LineComment("A comment");
-        aField.addOrphanComment(c);
-        // the comment is an orphan comment of the field, so trying to remove it on the class should not work
-        assertFalse(aClass.removeOrphanComment(c));
-        assertEquals(1, aField.getOrphanComments().size());
-        assertTrue(c.getParentNode().isPresent());
-    }
-
-    @Test
-    public void hasJavaDocCommentPositiveCaseWithSetJavaDocComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.setJavadocComment("A comment");
-        assertEquals(true, decl.hasJavaDocComment());
-    }
-
-    @Test
-    public void hasJavaDocCommentPositiveCaseWithSetComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.setComment(new JavadocComment("A comment"));
-        assertEquals(true, decl.hasJavaDocComment());
-    }
-
-    @Test
-    public void hasJavaDocCommentNegativeCaseNoComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        assertEquals(false, decl.hasJavaDocComment());
-    }
-
-    @Test
-    public void hasJavaDocCommentNegativeCaseLineComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.setComment(new LineComment("foo"));
-        assertEquals(false, decl.hasJavaDocComment());
-    }
-
-    @Test
-    public void hasJavaDocCommentNegativeCaseBlockComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.setComment(new BlockComment("foo"));
-        assertEquals(false, decl.hasJavaDocComment());
-    }
-
-    @Test
-    public void removeAllOnRequiredProperty() {
-        CompilationUnit cu = parse("class X{ void x(){}}");
-        MethodDeclaration methodDeclaration = cu.getType(0).getMethods().get(0);
-        methodDeclaration.getName().removeForced();
-        // Name is required, so to remove it the whole method is removed.
-        assertEquals(String.format("class X {%1$s}%1$s", EOL), cu.toString());
-    }
-
-    @Test
-    public void removingTheSecondOfAListOfIdenticalStatementsDoesNotMessUpTheParents() {
-        CompilationUnit unit = parse(String.format("public class Example {%1$s" +
-                "  public static void example() {%1$s" +
-                "    boolean swapped;%1$s" +
-                "    swapped=false;%1$s" +
-                "    swapped=false;%1$s" +
-                "  }%1$s" +
-                "}%1$s", EOL));
-        // remove the second swapped=false
-        Node target = unit.getChildNodes().get(0).getChildNodes().get(1).getChildNodes().get(2).getChildNodes().get(2);
-        target.remove();
-        // This will throw an exception if the parents are bad.
-        System.out.println(unit.toString());
-    }
-
-    @Test
-    public void findCompilationUnit() {
-        CompilationUnit cu = parse("class X{int x;}");
-        VariableDeclarator x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariables().get(0);
-        assertEquals(cu, x.findCompilationUnit().get());
-    }
-
-    @Test
-    public void findParent() {
-        CompilationUnit cu = parse("class X{int x;}");
-        SimpleName x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariables().get(0).getName();
-        assertEquals("int x;", x.findParent(FieldDeclaration.class).get().toString());
-    }
-
-    @Test
-    public void cantFindCompilationUnit() {
-        VariableDeclarator x = new VariableDeclarator();
-        assertFalse(x.findCompilationUnit().isPresent());
-    }
-
-    @Test
-    public void genericWalk() {
-        Expression e = parseExpression("1+1");
-        StringBuilder b = new StringBuilder();
-        e.walk(n -> b.append(n.toString()));
-        assertEquals("1 + 111", b.toString());
-    }
-
-    @Test
-    public void classSpecificWalk() {
-        Expression e = parseExpression("1+1");
-        StringBuilder b = new StringBuilder();
-        e.walk(IntegerLiteralExpr.class, n -> b.append(n.toString()));
-        assertEquals("11", b.toString());
-    }
-
-    @Test
-    public void conditionalFindAll() {
-        Expression e = parseExpression("1+2+3");
-        List<IntegerLiteralExpr> ints = e.findAll(IntegerLiteralExpr.class, n -> n.asInt() > 1);
-        assertEquals("[2, 3]", ints.toString());
-    }
-
-    @Test
-    public void typeOnlyFindAll() {
-        Expression e = parseExpression("1+2+3");
-        List<IntegerLiteralExpr> ints = e.findAll(IntegerLiteralExpr.class);
-        assertEquals("[1, 2, 3]", ints.toString());
-    }
-
-    @Test
-    public void typeOnlyFindAllMatchesSubclasses() {
-        Expression e = parseExpression("1+2+3");
-        List<Node> ints = e.findAll(Node.class);
-        assertEquals("[1 + 2 + 3, 1 + 2, 1, 2, 3]", ints.toString());
-    }
-
-    @Test
-    public void conditionalTypedFindFirst() {
-        Expression e = parseExpression("1+2+3");
-        Optional<IntegerLiteralExpr> ints = e.findFirst(IntegerLiteralExpr.class, n -> n.asInt() > 1);
-        assertEquals("Optional[2]", ints.toString());
-    }
-
-    @Test
-    public void typeOnlyFindFirst() {
-        Expression e = parseExpression("1+2+3");
-        Optional<IntegerLiteralExpr> ints = e.findFirst(IntegerLiteralExpr.class);
-        assertEquals("Optional[1]", ints.toString());
-    }
-    
-    @Test
-    public void stream() {
-        Expression e = parseExpression("1+2+3");
-        List<IntegerLiteralExpr> ints = e.stream()
-                .filter(n -> n instanceof IntegerLiteralExpr)
-                .map(IntegerLiteralExpr.class::cast)
-                .filter(i -> i.asInt() > 1)
-                .collect(Collectors.toList());
-        assertEquals("[2, 3]", ints.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java
deleted file mode 100644
index 45d7725..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/ParseResultTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.Problem;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.ast.Node.Parsedness.PARSED;
-import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ParseResultTest {
-    private final JavaParser javaParser = new JavaParser(new ParserConfiguration());
-
-    @Test
-    public void whenParsingSucceedsThenWeGetResultsAndNoProblems() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{}"));
-
-        assertThat(result.getResult().isPresent()).isTrue();
-        assertThat(result.getResult().get().getParsed()).isEqualTo(PARSED);
-        assertThat(result.getProblems()).isEmpty();
-        assertThat(result.getTokens().isPresent()).isTrue();
-
-        assertThat(result.toString()).isEqualTo("Parsing successful");
-    }
-
-    @Test
-    public void whenParsingFailsThenWeGetProblemsAndABadResult() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class {"));
-
-        assertThat(result.getResult().isPresent()).isTrue();
-        assertThat(result.getResult().get().getParsed()).isEqualTo(UNPARSABLE);
-        assertThat(result.getProblems().size()).isEqualTo(1);
-
-        Problem problem = result.getProblem(0);
-        assertThat(problem.getMessage()).isEqualTo("Parse error. Found \"{\", expected one of  \"enum\" \"exports\" \"module\" \"open\" \"opens\" \"provides\" \"requires\" \"strictfp\" \"to\" \"transitive\" \"uses\" \"with\" <IDENTIFIER>");
-        assertThat(result.getTokens().isPresent()).isTrue();
-
-        assertThat(result.toString()).startsWith("Parsing failed:" + EOL + "(line 1,col 1) Parse error.");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/ReplaceNodeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/ReplaceNodeTest.java
deleted file mode 100644
index 4e93efc..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/ReplaceNodeTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.github.javaparser.ast;
-
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parse;
-import static com.github.javaparser.JavaParser.parsePackageDeclaration;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class ReplaceNodeTest {
-    @Test
-    public void testSimplePropertyWithGenericReplace() {
-        CompilationUnit cu = parse("package x; class Y {}");
-        cu.replace(cu.getPackageDeclaration().get(), parsePackageDeclaration("package z;"));
-        assertEquals(String.format("package z;%1$s" +
-                "%1$s" +
-                "class Y {%1$s" +
-                "}%1$s", EOL), cu.toString());
-    }
-
-    @Test
-    public void testListProperty() {
-        CompilationUnit cu = parse("package x; class Y {}");
-        cu.replace(cu.getClassByName("Y").get(), parse("class B{int y;}").getClassByName("B").get());
-        assertEquals(String.format("package x;%1$s" +
-                "%1$s" +
-                "class B {%1$s" +
-                "%1$s" +
-                "    int y;%1$s" +
-                "}%1$s", EOL), cu.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/AnnotationMemberDeclarationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/body/AnnotationMemberDeclarationTest.java
deleted file mode 100644
index e133b50..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/AnnotationMemberDeclarationTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.body;
-
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.expr.SimpleName;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class AnnotationMemberDeclarationTest {
-
-    @Test
-    public void whenSettingNameTheParentOfNameIsAssigned() {
-        AnnotationMemberDeclaration decl = new AnnotationMemberDeclaration();
-        SimpleName name = new SimpleName("foo");
-        decl.setName(name);
-        assertTrue(name.getParentNode().isPresent());
-        assertTrue(decl == name.getParentNode().get());
-    }
-
-    @Test
-    public void removeDefaultValueWhenNoDefaultValueIsPresent() {
-        AnnotationMemberDeclaration decl = new AnnotationMemberDeclaration();
-        SimpleName name = new SimpleName("foo");
-        decl.setName(name);
-
-        decl.removeDefaultValue();
-
-        assertFalse(decl.getDefaultValue().isPresent());
-    }
-
-    @Test
-    public void removeDefaultValueWhenDefaultValueIsPresent() {
-        AnnotationMemberDeclaration decl = new AnnotationMemberDeclaration();
-        SimpleName name = new SimpleName("foo");
-        decl.setName(name);
-        Expression defaultValue = new IntegerLiteralExpr("2");
-        decl.setDefaultValue(defaultValue);
-
-        decl.removeDefaultValue();
-
-        assertFalse(defaultValue.getParentNode().isPresent());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java
deleted file mode 100644
index 52c77f1..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/ClassOrInterfaceDeclarationTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.github.javaparser.ast.body;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class ClassOrInterfaceDeclarationTest {
-    @Test
-    public void staticNestedClass() {
-        CompilationUnit cu = JavaParser.parse("class X{static class Y{}}");
-        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get().getMembers().get(0).asClassOrInterfaceDeclaration();
-
-        assertFalse(y.isInnerClass());
-        assertTrue(y.isNestedType());
-        assertFalse(y.isLocalClassDeclaration());
-    }
-
-    @Test
-    public void nestedInterface() {
-        CompilationUnit cu = JavaParser.parse("class X{interface Y{}}");
-        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get().getMembers().get(0).asClassOrInterfaceDeclaration();
-
-        assertFalse(y.isInnerClass());
-        assertTrue(y.isNestedType());
-        assertFalse(y.isLocalClassDeclaration());
-    }
-
-    @Test
-    public void nonStaticNestedClass() {
-        CompilationUnit cu = JavaParser.parse("class X{class Y{}}");
-        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get().getMembers().get(0).asClassOrInterfaceDeclaration();
-
-        assertTrue(y.isInnerClass());
-        assertTrue(y.isNestedType());
-        assertFalse(y.isLocalClassDeclaration());
-    }
-
-    @Test
-    public void topClass() {
-        CompilationUnit cu = JavaParser.parse("class X{}");
-        ClassOrInterfaceDeclaration y = cu.getClassByName("X").get();
-
-        assertFalse(y.isInnerClass());
-        assertFalse(y.isNestedType());
-        assertFalse(y.isLocalClassDeclaration());
-    }
-
-    @Test
-    public void localClass() {
-        MethodDeclaration method= (MethodDeclaration)JavaParser.parseBodyDeclaration("void x(){class X{};}");
-        ClassOrInterfaceDeclaration x = method.findFirst(ClassOrInterfaceDeclaration.class).get();
-
-        assertFalse(x.isInnerClass());
-        assertFalse(x.isNestedType());
-        assertTrue(x.isLocalClassDeclaration());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/ConstructorDeclarationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/body/ConstructorDeclarationTest.java
deleted file mode 100644
index 34d3b62..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/ConstructorDeclarationTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.github.javaparser.ast.body;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.CLASS_BODY;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class ConstructorDeclarationTest {
-    @Test
-    public void acceptsSuper() {
-        ConstructorDeclaration cons = new ConstructorDeclaration("Cons");
-        cons.createBody().addStatement("super();");
-
-        assertEquals(String.format("public Cons() {%1$s" +
-                "    super();%1$s" +
-                "}", EOL), cons.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java
deleted file mode 100644
index 0e263a4..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/FieldDeclarationTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.github.javaparser.ast.body;
-
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parse;
-import static org.junit.Assert.assertEquals;
-
-public class FieldDeclarationTest {
-    @Test
-    public void wofjweoifj() {
-        CompilationUnit compilationUnit = parse("" +
-                "class A {\n" +
-                "    int a, b;\n" +
-                "}");
-
-        BodyDeclaration<?> declaration = compilationUnit.getType(0).getMembers().get(0);
-        FieldDeclaration fieldDeclaration = declaration.asFieldDeclaration();
-        VariableDeclarator var1 = fieldDeclaration.getVariables().get(0);
-        VariableDeclarator var2 = fieldDeclaration.getVariables().get(1);
-        assertEquals(var1, var1.getType().getParentNode().get());
-        assertEquals(var2, var2.getType().getParentNode().get());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/MethodDeclarationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/body/MethodDeclarationTest.java
deleted file mode 100644
index 1cbab66..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/body/MethodDeclarationTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.github.javaparser.ast.body;
-
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseBodyDeclaration;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-
-public class MethodDeclarationTest {
-    @Test
-    public void annotationsAllowedAfterGenericsAndBeforeReturnType() {
-        parseBodyDeclaration("public <T> @Abc String method() {return null;}");
-    }
-
-    @Test
-    public void annotationsAllowedBeforeGenerics() {
-        parseBodyDeclaration("public @Abc <T> String method() {return null;}");
-    }
-
-    @Test
-    public void explicitReceiverParameters1() {
-        MethodDeclaration method = parseBodyDeclaration("void InnerInner(@mypackage.Anno Source.@mypackage.Anno Inner Source.Inner.this) { }").asMethodDeclaration();
-        assertEquals("Source.Inner.this", method.getReceiverParameter().get().getNameAsString());
-    }
-
-    @Test
-    public void explicitReceiverParameters2() {
-        MethodDeclaration method = parseBodyDeclaration("void x(A this) { }").asMethodDeclaration();
-        assertEquals("this", method.getReceiverParameter().get().getNameAsString());
-    }
-
-    @Test
-    public void explicitReceiverParameters3() {
-        MethodDeclaration method = parseBodyDeclaration("void x(A that) { }").asMethodDeclaration();
-        assertFalse(method.getReceiverParameter().isPresent());
-    }
-
-    @Test
-    public void signaturesEqual() {
-        MethodDeclaration method1 = parseBodyDeclaration("void x(String a) { }").asMethodDeclaration();
-        MethodDeclaration method2 = parseBodyDeclaration("int x(String z);").asMethodDeclaration();
-        assertEquals(method1.getSignature(), method2.getSignature());
-    }
-
-    @Test
-    public void signaturesEqualWhenGenericsDiffer() {
-        MethodDeclaration method1 = parseBodyDeclaration("void x(List<Long> a) { }").asMethodDeclaration();
-        MethodDeclaration method2 = parseBodyDeclaration("void x(List<Integer> a) { }").asMethodDeclaration();
-        assertEquals(method1.getSignature(), method2.getSignature());
-    }
-
-    @Test
-    public void signaturesEqualWhenAnnotationsDiffer() {
-        MethodDeclaration method1 = parseBodyDeclaration("void x(@A @B List a) { }").asMethodDeclaration();
-        MethodDeclaration method2 = parseBodyDeclaration("void x(@C List a) { }").asMethodDeclaration();
-        assertEquals(method1.getSignature(), method2.getSignature());
-    }
-
-    @Test
-    public void signaturesDifferentName() {
-        MethodDeclaration method1 = parseBodyDeclaration("void x(String a) { }").asMethodDeclaration();
-        MethodDeclaration method2 = parseBodyDeclaration("int y(String z);").asMethodDeclaration();
-        assertNotEquals(method1.getSignature(), method2.getSignature());
-    }
-
-    @Test
-    public void signaturesDifferentTypes() {
-        MethodDeclaration method1 = parseBodyDeclaration("void x(String a) { }").asMethodDeclaration();
-        MethodDeclaration method2 = parseBodyDeclaration("int x(int z);").asMethodDeclaration();
-        assertNotEquals(method1.getSignature(), method2.getSignature());
-    }
-
-    @Test
-    public void signaturesDifferentVarargs() {
-        MethodDeclaration method1 = parseBodyDeclaration("int x(int z);").asMethodDeclaration();
-        MethodDeclaration method2 = parseBodyDeclaration("int x(int... z);").asMethodDeclaration();
-        assertNotEquals(method1.getSignature(), method2.getSignature());
-    }
-
-    @Test
-    public void signatureToString() {
-        MethodDeclaration method1 = parseBodyDeclaration("int x(int z, String q);").asMethodDeclaration();
-        assertEquals("x(int, String)", method1.getSignature().toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/comments/CommentTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/comments/CommentTest.java
deleted file mode 100644
index 946b76a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/comments/CommentTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.comments;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.expr.Name;
-import org.junit.Test;
-
-import java.util.EnumSet;
-
-import static com.github.javaparser.JavaParser.parse;
-import static com.github.javaparser.JavaParser.parseName;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class CommentTest {
-
-    @Test
-    public void removeOrphanComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class), false, "A");
-        Comment c = new LineComment("A comment");
-        decl.addOrphanComment(c);
-        assertEquals(1, decl.getOrphanComments().size());
-        assertTrue(c.remove());
-        assertEquals(0, decl.getOrphanComments().size());
-    }
-
-    @Test
-    public void removeAssociatedComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class), false, "A");
-        Comment c = new LineComment("A comment");
-        decl.setComment(c);
-        assertEquals(true, decl.getComment().isPresent());
-        assertTrue(c.remove());
-        assertEquals(false, decl.getComment().isPresent());
-    }
-
-    @Test
-    public void cannotRemoveCommentNotUsedAnywhere() {
-        Comment c = new LineComment("A comment");
-        assertFalse(c.remove());
-    }
-
-    @Test
-    public void unicodeEscapesArePreservedInComments() {
-        CompilationUnit cu = parse("// xxx\\u2122xxx");
-        Comment comment = cu.getAllContainedComments().get(0);
-        assertEquals(" xxx\\u2122xxx", comment.getContent());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/AssignExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/AssignExprTest.java
deleted file mode 100644
index 55e87f5..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/AssignExprTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import org.junit.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class AssignExprTest {
-    @Test
-    public void convertOperator() {
-        assertEquals(BinaryExpr.Operator.PLUS, AssignExpr.Operator.PLUS.toBinaryOperator().get());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/BinaryExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/BinaryExprTest.java
deleted file mode 100644
index 9975ef3..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/BinaryExprTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import org.junit.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class BinaryExprTest {
-    @Test
-    public void convertOperator() {
-        assertEquals(AssignExpr.Operator.PLUS, BinaryExpr.Operator.PLUS.toAssignOperator().get());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/DoubleLiteralExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/DoubleLiteralExprTest.java
deleted file mode 100644
index 9c54643..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/DoubleLiteralExprTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseExpression;
-
-public class DoubleLiteralExprTest {
-    @Test
-    public void test1() {
-        float x = 0x0.00_00_02p-126f;
-        parseExpression("0x0.00_00_02p-126f");
-    }
-
-    @Test
-    public void test2() {
-        double x = 0x0.000_000_000_000_1p-1_022;
-        parseExpression("0x0.000_000_000_000_1p-1_022");
-    }
-
-    @Test
-    public void test3() {
-        double a = 0x1.p+1;
-        parseExpression("0x1.p+1");
-    }
-
-    @Test
-    public void test4() {
-        double a = 0x.0p0;
-        parseExpression("0x.0p0");
-    }
-
-    @Test
-    public void test5() {
-        double x = 0x0_0.0_0p-1_0;
-        parseExpression("0x0_0.0_0p-1_0");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/InstanceOfExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/InstanceOfExprTest.java
deleted file mode 100644
index 0d8a5b9..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/InstanceOfExprTest.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import com.github.javaparser.JavaParser;
-import org.junit.Test;
-
-import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
-
-public class InstanceOfExprTest {
-    @Test
-    public void annotationsOnTheType() {
-        InstanceOfExpr expr = JavaParser.parseExpression("s instanceof @A @DA String");
-
-        assertThat(expr.getType().getAnnotations()).containsExactly(new MarkerAnnotationExpr("A"), new MarkerAnnotationExpr("DA"));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/LambdaExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/LambdaExprTest.java
deleted file mode 100644
index 082906b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/LambdaExprTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import com.github.javaparser.TokenRange;
-import com.github.javaparser.ast.Node;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseExpression;
-import static org.junit.Assert.*;
-
-public class LambdaExprTest {
-    @Test
-    public void lambdaRange1(){
-        Expression expression = parseExpression("x -> y");
-        assertRange("x", "y", expression);
-    }
-
-    @Test
-    public void lambdaRange2(){
-        Expression expression = parseExpression("(x) -> y");
-        assertRange("(", "y", expression);
-    }
-
-    private void assertRange(String startToken, String endToken, Node node) {
-        TokenRange tokenRange = node.getTokenRange().get();
-        assertEquals(startToken, tokenRange.getBegin().asString());
-        assertEquals(endToken, tokenRange.getEnd().asString());
-    }
-
-    @Test
-    public void getExpressionBody(){
-        LambdaExpr lambdaExpr = parseExpression("x -> y").asLambdaExpr();
-        assertEquals("Optional[y]", lambdaExpr.getExpressionBody().toString());
-    }
-
-    @Test
-    public void getNoExpressionBody(){
-        LambdaExpr lambdaExpr = parseExpression("x -> {y;}").asLambdaExpr();
-        assertEquals("Optional.empty", lambdaExpr.getExpressionBody().toString());
-    }
-
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/LiteralStringValueExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/LiteralStringValueExprTest.java
deleted file mode 100644
index 1b9dfef..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/LiteralStringValueExprTest.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
- * Copyright (C) 2011, 2013-2017 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.expr;
-
-import com.github.javaparser.JavaParser;
-import org.assertj.core.data.Percentage;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.*;
-import static org.assertj.core.api.Assertions.assertThat;
-
-@SuppressWarnings("OctalInteger")
-public class LiteralStringValueExprTest {
-
-    @Test
-    public void trivialLiteralsAreConverted() {
-        assertThat(new CharLiteralExpr('\t').getValue()).isEqualTo("\\t");
-        assertThat(new CharLiteralExpr('\b').getValue()).isEqualTo("\\b");
-        assertThat(new CharLiteralExpr('\f').getValue()).isEqualTo("\\f");
-        assertThat(new CharLiteralExpr('\r').getValue()).isEqualTo("\\r");
-        assertThat(new CharLiteralExpr('\n').getValue()).isEqualTo("\\n");
-        assertThat(new CharLiteralExpr('\\').getValue()).isEqualTo("\\\\");
-        assertThat(new CharLiteralExpr('\"').getValue()).isEqualTo("\\\"");
-
-        assertThat(new IntegerLiteralExpr("0B0").asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr("0b0").asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr("0X0").asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr("0x0").asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr(0).asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr(00).asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr(0B0).asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr(0b0).asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr(0X0).asInt()).isEqualTo(0);
-        assertThat(new IntegerLiteralExpr(0x0).asInt()).isEqualTo(0);
-
-        assertThat(new LongLiteralExpr("0B0L").asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr("0b0L").asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr("0X0L").asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr("0x0L").asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr(0L).asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr(00L).asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr(0B0L).asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr(0b0L).asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr(0X0L).asLong()).isEqualTo(0);
-        assertThat(new LongLiteralExpr(0x0L).asLong()).isEqualTo(0);
-
-        assertThat(new DoubleLiteralExpr("0.0f").asDouble()).isEqualTo(0.0);
-        assertThat(new DoubleLiteralExpr("0.0F").asDouble()).isEqualTo(0.0);
-        assertThat(new DoubleLiteralExpr("0.0d").asDouble()).isEqualTo(0.0);
-        assertThat(new DoubleLiteralExpr("0.0D").asDouble()).isEqualTo(0.0);
-        assertThat(new DoubleLiteralExpr(0.0F).asDouble()).isEqualTo(0.0);
-        assertThat(new DoubleLiteralExpr(0.0f).asDouble()).isEqualTo(0.0);
-        assertThat(new DoubleLiteralExpr(0.0D).asDouble()).isEqualTo(0.0);
-        assertThat(new DoubleLiteralExpr(0.0d).asDouble()).isEqualTo(0.0);
-    }
-
-    @Test
-    public void lowerAndUpperBoundIntegersAreConverted() {
-        IntegerLiteralExpr dec = parseExpression("2147483647");
-        IntegerLiteralExpr posOct = parseExpression("0177_7777_7777");
-        IntegerLiteralExpr negOct = parseExpression("0377_7777_7777");
-        IntegerLiteralExpr posHex = parseExpression("0x7fff_ffff");
-        IntegerLiteralExpr negHex = parseExpression("0xffff_ffff");
-        IntegerLiteralExpr posBin = parseExpression("0b0111_1111_1111_1111_1111_1111_1111_1111");
-        IntegerLiteralExpr negBin = parseExpression("0b1000_0000_0000_0000_0000_0000_0000_0000");
-
-        assertThat(dec.asInt()).isEqualTo(2147483647);
-        assertThat(posOct.asInt()).isEqualTo(2147483647); // 0177_7777_7777
-        assertThat(negOct.asInt()).isEqualTo(-1); // 0377_7777_7777
-        assertThat(posHex.asInt()).isEqualTo(0x7fff_ffff);
-        assertThat(negHex.asInt()).isEqualTo(0xffff_ffff);
-        assertThat(posBin.asInt()).isEqualTo(0b0111_1111_1111_1111_1111_1111_1111_1111);
-        assertThat(negBin.asInt()).isEqualTo(0b1000_0000_0000_0000_0000_0000_0000_0000);
-    }
-
-    @Test
-    public void lowerAndUpperBoundLongsAreConverted() {
-        LongLiteralExpr dec = parseExpression("9223372036854775807L");
-        LongLiteralExpr posOct = parseExpression("07_7777_7777_7777_7777_7777L");
-        LongLiteralExpr negOct = parseExpression("010_0000_0000_0000_0000_0000L");
-        LongLiteralExpr posHex = parseExpression("0x7fff_ffff_ffff_ffffL");
-        LongLiteralExpr negHex = parseExpression("0xffff_ffff_ffff_ffffL");
-        LongLiteralExpr posBin = parseExpression("0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L");
-        LongLiteralExpr negBin = parseExpression("0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L");
-
-        assertThat(dec.asLong()).isEqualTo(9223372036854775807L);
-        assertThat(posOct.asLong()).isEqualTo(9223372036854775807L); // 07_7777_7777_7777_7777_7777L
-        assertThat(negOct.asLong()).isEqualTo(-9223372036854775808L); // 010_0000_0000_0000_0000_0000L
-        assertThat(posHex.asLong()).isEqualTo(0x7fff_ffff_ffff_ffffL);
-        assertThat(negHex.asLong()).isEqualTo(0xffff_ffff_ffff_ffffL);
-        assertThat(posBin.asLong()).isEqualTo(0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L);
-        assertThat(negBin.asLong()).isEqualTo(0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L);
-    }
-
-    @Test
-    public void charLiteralsAreConverted() {
-        CharLiteralExpr a = parseExpression("'a'");
-        CharLiteralExpr percent = parseExpression("'%'");
-        CharLiteralExpr tab = parseExpression("'\\t'");
-        CharLiteralExpr newLine = parseExpression("'\\n'");
-        CharLiteralExpr slash = parseExpression("'\\\\'");
-        CharLiteralExpr quote = parseExpression("'\\''");
-        CharLiteralExpr omega = parseExpression("'\\u03a9'");
-        CharLiteralExpr unicode = parseExpression("'\\uFFFF'");
-        CharLiteralExpr ascii = parseExpression("'\\177'");
-        CharLiteralExpr trademark = parseExpression("'™'");
-
-        assertThat(a.asChar()).isEqualTo('a');
-        assertThat(percent.asChar()).isEqualTo('%');
-        assertThat(tab.asChar()).isEqualTo('\t');
-        assertThat(newLine.asChar()).isEqualTo('\n');
-        assertThat(slash.asChar()).isEqualTo('\\');
-        assertThat(quote.asChar()).isEqualTo('\'');
-        assertThat(omega.asChar()).isEqualTo('\u03a9');
-        assertThat(unicode.asChar()).isEqualTo('\uFFFF');
-        assertThat(ascii.asChar()).isEqualTo('\177');
-        assertThat(trademark.asChar()).isEqualTo('™');
-    }
-
-    @Test
-    public void lowerAndUpperBoundDoublesAreConverted() {
-        DoubleLiteralExpr posFloat = parseExpression("3.4028235e38f");
-        DoubleLiteralExpr negFloat = parseExpression("1.40e-45f");
-        DoubleLiteralExpr posDouble = parseExpression("1.7976931348623157e308");
-        DoubleLiteralExpr negDouble = parseExpression("4.9e-324");
-        DoubleLiteralExpr posHexFloat = parseExpression("0x1.fffffffffffffp1023");
-        DoubleLiteralExpr negHexFloat = parseExpression("0x0.0000000000001P-1022");
-
-        assertThat(posFloat.asDouble()).isCloseTo(3.4028235e38f, Percentage.withPercentage(1));
-        assertThat(negFloat.asDouble()).isCloseTo(1.40e-45f, Percentage.withPercentage(1));
-        assertThat(posDouble.asDouble()).isEqualTo(1.7976931348623157e308);
-        assertThat(negDouble.asDouble()).isEqualTo(4.9e-324);
-        assertThat(posHexFloat.asDouble()).isEqualTo(0x1.fffffffffffffp1023);
-        assertThat(negHexFloat.asDouble()).isEqualTo(0x0.0000000000001P-1022);
-    }
-
-    @Test
-    public void specialCharactersInStringsAreEscaped() {
-        assertThat(new StringLiteralExpr("\n").getValue()).isEqualTo("\\n");
-        assertThat(new StringLiteralExpr("\r").getValue()).isEqualTo("\\r");
-        assertThat(new StringLiteralExpr("").setEscapedValue("\n").getValue()).isEqualTo("\\n");
-        assertThat(new StringLiteralExpr("").setEscapedValue("\r").getValue()).isEqualTo("\\r");
-        assertThat(new StringLiteralExpr("").setEscapedValue("\n").asString()).isEqualTo("\n");
-        assertThat(new StringLiteralExpr("").setEscapedValue("\r").asString()).isEqualTo("\r");
-        assertThat(new StringLiteralExpr("Hello\nWorld\rHello\"World\'").asString()).isEqualTo("Hello\nWorld\rHello\"World\'");
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/MethodCallExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/MethodCallExprTest.java
deleted file mode 100644
index 2585764..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/MethodCallExprTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseExpression;
-import static java.util.Optional.empty;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class MethodCallExprTest {
-    
-    @Test
-    public void replaceLambdaIssue1290() {
-        MethodCallExpr methodCallExpr = parseExpression("callSomeFun(r -> r instanceof SomeType)").asMethodCallExpr();
-        LambdaExpr lambdaExpr = methodCallExpr.getArgument(0).asLambdaExpr();
-        MethodCallExpr lambdaWrapper = new MethodCallExpr("lambdaWrapper");
-        lambdaExpr.replace(lambdaWrapper);
-        
-        assertEquals(2, methodCallExpr.getChildNodes().size());
-        assertEquals(empty(), lambdaExpr.getParentNode());
-    }
-
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/MethodReferenceExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/MethodReferenceExprTest.java
deleted file mode 100644
index 6f0643b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/MethodReferenceExprTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import org.junit.Test;
-
-import static com.github.javaparser.utils.TestUtils.assertExpressionValid;
-import static org.junit.Assert.assertTrue;
-
-public class MethodReferenceExprTest {
-
-    @Test
-    public void methodReferenceExprHasAlwaysAScope() {
-        assertTrue(new MethodReferenceExpr().getScope() != null);
-    }
-
-    @Test
-    public void reference1() {
-        assertExpressionValid("String::length");
-    }
-        
-    @Test
-    public void reference2() {
-        assertExpressionValid("System::currentTimeMillis // static method");
-    }
-        
-    @Test
-    public void reference3() {
-        assertExpressionValid("List<String>::size // explicit type arguments for generic type");
-    }
-        
-    @Test
-    public void reference4() {
-        assertExpressionValid("List::size // inferred type arguments for generic type");
-    }
-        
-    @Test
-    public void reference5() {
-        assertExpressionValid("int[]::clone");
-    }
-        
-    @Test
-    public void reference6() {
-        assertExpressionValid("T::tvarMember");
-    }
-        
-    @Test
-    public void reference7() {
-        assertExpressionValid("System.out::println");
-    }
-        
-    @Test
-    public void reference8() {
-        assertExpressionValid("\"abc\"::length");
-    }
-        
-    @Test
-    public void reference9() {
-        assertExpressionValid("foo[x]::bar");
-    }
-        
-    @Test
-    public void reference10() {
-        assertExpressionValid("(test ? list.replaceAll(String::trim) : list) :: iterator");
-    }
-        
-    @Test
-    public void reference10Annotated1() {
-        assertExpressionValid("(test ? list.replaceAll(@A String::trim) : list) :: iterator");
-    }
-        
-    @Test
-    public void reference11() {
-        assertExpressionValid("String::valueOf // overload resolution needed");
-    }
-        
-    @Test
-    public void reference12() {
-        assertExpressionValid("Arrays::sort // type arguments inferred from context");
-    }
-        
-    @Test
-    public void reference13() {
-        assertExpressionValid("Arrays::<String>sort // explicit type arguments");
-    }
-        
-    @Test
-    public void reference14() {
-        assertExpressionValid("ArrayList<String>::new // constructor for parameterized type");
-    }
-        
-    @Test
-    public void reference15() {
-        assertExpressionValid("ArrayList::new // inferred type arguments");
-    }
-        
-    @Test
-    public void reference16() {
-        assertExpressionValid("Foo::<Integer>new // explicit type arguments");
-    }
-        
-    @Test
-    public void reference17() {
-        assertExpressionValid("Bar<String>::<Integer>new // generic class, generic constructor");
-    }
-        
-    @Test
-    public void reference18() {
-        assertExpressionValid("Outer.Inner::new // inner class constructor");
-    }
-        
-    @Test
-    public void reference19() {
-        assertExpressionValid("int[]::new // array creation");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/NameTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/NameTest.java
deleted file mode 100644
index 6df3a68..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/NameTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
- * Copyright (C) 2011, 2013-2017 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.expr;
-
-import com.github.javaparser.ParseProblemException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.ImportDeclaration;
-import com.github.javaparser.printer.ConcreteSyntaxModel;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.*;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
-import static org.junit.Assert.assertEquals;
-
-public class NameTest {
-    @Test
-    public void outerNameExprIsTheRightMostIdentifier() {
-        Name name = parseName("a.b.c");
-        assertEquals("c", name.getIdentifier());
-    }
-
-    @Test
-    public void parsingAndUnparsingWorks() {
-        Name name = parseName("a.b.c");
-        assertEquals("a.b.c", name.asString());
-    }
-
-    @Test(expected = ParseProblemException.class)
-    public void parsingEmptyNameThrowsException() {
-        parseName("");
-    }
-
-    @Test
-    public void nameCanHaveAnnotationsInside() {
-        Name name = parseName("a.@A b. @C c");
-        assertEquals("a.b.c", name.asString());
-        assertThat(name.getAnnotations()).containsExactly(new MarkerAnnotationExpr("C"));
-        assertThat(name.getQualifier().get().getAnnotations()).containsExactly(new MarkerAnnotationExpr("A"));
-
-        assertEquals("a.@A b.@C c", name.toString());
-        assertEquals("a.@A b.@C c", ConcreteSyntaxModel.genericPrettyPrint(name));
-    }
-
-    @Test
-    public void importName() {
-        ImportDeclaration importDeclaration = parseImport("import java.@Abc util.List;");
-
-        assertThat(importDeclaration.getName().getQualifier().get().getAnnotations()).containsExactly(new MarkerAnnotationExpr("Abc"));
-
-        assertEquals("import java.@Abc util.List;" + EOL, importDeclaration.toString());
-        assertEquals("import java.@Abc util.List;" + EOL, ConcreteSyntaxModel.genericPrettyPrint(importDeclaration));
-    }
-
-    @Test
-    public void packageName() {
-        CompilationUnit cu = parse("package @Abc p1.p2;");
-
-        assertThat(cu.getPackageDeclaration().get().getName().getQualifier().get().getAnnotations()).containsExactly(new MarkerAnnotationExpr("Abc"));
-
-        assertEquals("package @Abc p1.p2;" + EOL + EOL, cu.toString());
-        assertEquals("package @Abc p1.p2;" + EOL + EOL, ConcreteSyntaxModel.genericPrettyPrint(cu));
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/SimpleNameTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/SimpleNameTest.java
deleted file mode 100644
index f7e0285..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/SimpleNameTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
- * Copyright (C) 2011, 2013-2017 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.expr;
-
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseSimpleName;
-import static junit.framework.TestCase.assertEquals;
-
-public class SimpleNameTest {
-
-    @Test
-    public void defaultConstructorSetsIdentifierToEmpty() {
-        assertEquals("empty", new SimpleName().getIdentifier());
-    }
-
-    @Test(expected = AssertionError.class)
-    public void identifierMustNotBeEmpty() {
-        new SimpleName("");
-    }
-
-    @Test(expected = AssertionError.class)
-    public void identifierMustNotBeNull() {
-        new SimpleName(null);
-    }
-
-    @Test
-    public void unicodeEscapesArePreservedInIdentifiers() {
-        SimpleName name = parseSimpleName("xxx\\u2122xxx");
-        assertEquals("xxx\\u2122xxx", name.asString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/StringLiteralExprTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/StringLiteralExprTest.java
deleted file mode 100644
index 50a9bfc..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/expr/StringLiteralExprTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.github.javaparser.ast.expr;
-
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseExpression;
-import static org.junit.Assert.*;
-
-public class StringLiteralExprTest {
-    @Test
-    public void unicodeEscapesArePreservedInStrings() {
-        StringLiteralExpr omega = parseExpression("\"xxx\\u03a9xxx\"");
-        assertEquals("xxx\\u03a9xxx", omega.getValue());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/imports/ImportDeclarationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/imports/ImportDeclarationTest.java
deleted file mode 100644
index ca821fb..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/imports/ImportDeclarationTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.imports;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.ImportDeclaration;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class ImportDeclarationTest {
-    @Test
-    public void singleTypeImportDeclaration() {
-        ImportDeclaration i = JavaParser.parseImport("import a.b.c.X;");
-        assertEquals("a.b.c.X", i.getNameAsString());
-    }
-
-    @Test
-    public void typeImportOnDemandDeclaration() {
-        ImportDeclaration i = JavaParser.parseImport("import a.b.c.D.*;");
-        assertEquals("a.b.c.D", i.getName().toString());
-        assertEquals("D", i.getName().getIdentifier());
-    }
-
-    @Test
-    public void singleStaticImportDeclaration() {
-        ImportDeclaration i = JavaParser.parseImport("import static a.b.c.X.def;");
-        assertEquals("a.b.c.X", i.getName().getQualifier().get().asString());
-        assertEquals("def", i.getName().getIdentifier());
-    }
-
-    @Test
-    public void staticImportOnDemandDeclaration() {
-        ImportDeclaration i = JavaParser.parseImport("import static a.b.c.X.*;");
-        assertEquals("a.b.c.X", i.getNameAsString());
-    }
-
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadocTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadocTest.java
deleted file mode 100644
index 37728e7..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithJavadocTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
- * Copyright (C) 2011, 2013-2017 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.nodeTypes;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.ast.comments.LineComment;
-import org.junit.Test;
-
-import java.util.EnumSet;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class NodeWithJavadocTest {
-
-    @Test
-    public void removeJavaDocNegativeCaseNoComment() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        assertEquals(false, decl.removeJavaDocComment());
-    }
-
-    @Test
-    public void removeJavaDocNegativeCaseCommentNotJavaDoc() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.setComment(new LineComment("A comment"));
-        assertEquals(false, decl.removeJavaDocComment());
-        assertTrue(decl.getComment().isPresent());
-    }
-
-    @Test
-    public void removeJavaDocPositiveCase() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.setComment(new JavadocComment("A comment"));
-        assertEquals(true, decl.removeJavaDocComment());
-        assertFalse(decl.getComment().isPresent());
-    }
-
-    @Test
-    public void getJavadocOnMethodWithLineCommentShouldReturnEmptyOptional() {
-        MethodDeclaration method = new MethodDeclaration();
-        method.setLineComment("Lorem Ipsum.");
-
-        assertFalse(method.getJavadocComment().isPresent());
-        assertFalse(method.getJavadoc().isPresent());
-    }
-
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiersTest.java
deleted file mode 100644
index 20c302d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithModifiersTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
- * Copyright (C) 2011, 2013-2017 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.nodeTypes;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.ast.comments.LineComment;
-import com.github.javaparser.ast.observer.AstObserverAdapter;
-import com.github.javaparser.ast.observer.ObservableProperty;
-import org.junit.Test;
-
-import java.util.EnumSet;
-import java.util.LinkedList;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
-public class NodeWithModifiersTest {
-
-    @Test
-    public void addModifierWorks() {
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.addModifier(Modifier.PUBLIC);
-        assertEquals(EnumSet.of(Modifier.PUBLIC), decl.getModifiers());
-    }
-
-    @Test
-    public void addModifierTriggerNotification() {
-        List<String> changes = new LinkedList<>();
-        ClassOrInterfaceDeclaration decl = new ClassOrInterfaceDeclaration(EnumSet.noneOf(Modifier.class),
-                false, "Foo");
-        decl.register(new AstObserverAdapter() {
-            @Override
-            public void propertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add("property " + property.name() + " is changed to " + newValue);
-            }
-        });
-        decl.addModifier(Modifier.PUBLIC);
-        assertEquals(1, changes.size());
-        assertEquals("property MODIFIERS is changed to [PUBLIC]", changes.get(0));
-    }
-
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithOptionalScopeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithOptionalScopeTest.java
deleted file mode 100644
index ad7e8bd..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithOptionalScopeTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.github.javaparser.ast.nodeTypes;
-
-import com.github.javaparser.ast.expr.*;
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class NodeWithOptionalScopeTest {
-
-    @Test
-    public void commonExpressionWhichHaveInterfaceNodeWithOptionalScope() {
-        NodeWithOptionalScope methodCallExpr = new MethodCallExpr(new NameExpr("A"), "call");
-        NodeWithOptionalScope objectCreationExpr = new ObjectCreationExpr();
-
-        assertTrue(methodCallExpr.getScope().isPresent());
-        assertFalse(objectCreationExpr.getScope().isPresent());
-    }
-
-    @Test
-    public void removeScope() {
-        MethodCallExpr methodCallExpr = new MethodCallExpr(new NameExpr("A"), "method");
-
-        methodCallExpr.removeScope();
-
-        assertFalse(methodCallExpr.getScope().isPresent());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithTraversableScopeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithTraversableScopeTest.java
deleted file mode 100644
index 59aaf4e..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithTraversableScopeTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.github.javaparser.ast.nodeTypes;
-
-import com.github.javaparser.ast.expr.FieldAccessExpr;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseExpression;
-import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
-import static org.junit.Assert.assertFalse;
-
-public class NodeWithTraversableScopeTest {
-    @Test
-    public void traverse1() {
-        NodeWithTraversableScope expression = parseExpression("getAddress().name.startsWith(\"abc\")");
-
-        assertInstanceOf(MethodCallExpr.class, expression);
-        expression = (NodeWithTraversableScope) expression.traverseScope().get();
-        assertInstanceOf(FieldAccessExpr.class, expression);
-        expression = (NodeWithTraversableScope) expression.traverseScope().get();
-        assertInstanceOf(MethodCallExpr.class, expression);
-        assertFalse(expression.traverseScope().isPresent());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithVariablesTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithVariablesTest.java
deleted file mode 100644
index b736333..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/nodeTypes/NodeWithVariablesTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.nodeTypes;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.type.PrimitiveType;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.*;
-import static org.junit.Assert.assertEquals;
-
-public class NodeWithVariablesTest {
-
-    @Test
-    public void getCommonTypeWorksForNormalVariables() {
-        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
-        assertEquals(PrimitiveType.intType(), declaration.getCommonType());
-    }
-
-    @Test
-    public void getCommonTypeWorksForArrayTypes() {
-        parseVariableDeclarationExpr("int a[],b[]").getCommonType();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void getCommonTypeFailsOnArrayDifferences() {
-        parseVariableDeclarationExpr("int a[],b[][]").getCommonType();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void getCommonTypeFailsOnDodgySetterUsage() {
-        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
-        declaration.getVariable(1).setType(String.class);
-        declaration.getCommonType();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void getCommonTypeFailsOnInvalidEmptyVariableList() {
-        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a");
-        declaration.getVariables().clear();
-        declaration.getCommonType();
-    }
-
-    @Test
-    public void getElementTypeWorksForNormalVariables() {
-        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
-        assertEquals(PrimitiveType.intType(), declaration.getElementType());
-    }
-
-    @Test
-    public void getElementTypeWorksForArrayTypes() {
-        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a[],b[]");
-        assertEquals(PrimitiveType.intType(), declaration.getElementType());
-    }
-
-    @Test
-    public void getElementTypeIsOkayWithArrayDifferences() {
-        parseVariableDeclarationExpr("int a[],b[][]").getElementType();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void getElementTypeFailsOnDodgySetterUsage() {
-        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a,b");
-        declaration.getVariable(1).setType(String.class);
-        declaration.getElementType();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void getElementTypeFailsOnInvalidEmptyVariableList() {
-        VariableDeclarationExpr declaration = parseVariableDeclarationExpr("int a");
-        declaration.getVariables().clear();
-        declaration.getElementType();
-    }
-
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/observer/PropagatingAstObserverTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/observer/PropagatingAstObserverTest.java
deleted file mode 100644
index b590f32..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/observer/PropagatingAstObserverTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.observer;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class PropagatingAstObserverTest {
-    @Test
-    public void verifyPropagation() {
-        String code = "class A {  }";
-        CompilationUnit cu = JavaParser.parse(code);
-        List<String> changes = new ArrayList<>();
-        AstObserver observer = new PropagatingAstObserver() {
-            @Override
-            public void concretePropertyChange(Node observedNode, ObservableProperty property, Object oldValue, Object newValue) {
-                changes.add(String.format("%s.%s changed from %s to %s", observedNode.getClass().getSimpleName(), property.name().toLowerCase(), oldValue, newValue));
-            }
-        };
-        cu.registerForSubtree(observer);
-
-        assertEquals(Arrays.asList(), changes);
-
-        FieldDeclaration fieldDeclaration = cu.getClassByName("A").get().addField("String", "foo");
-        assertEquals(Arrays.asList(), changes);
-        assertEquals(true, fieldDeclaration.isRegistered(observer));
-
-        cu.getClassByName("A").get().getFieldByName("foo").get().getVariables().get(0).setName("Bar");
-        assertEquals(Arrays.asList("VariableDeclarator.name changed from foo to Bar"), changes);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/BlockStmtTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/BlockStmtTest.java
deleted file mode 100644
index 5e5976a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/BlockStmtTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.github.javaparser.ast.stmt;
-
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.expr.NameExpr;
-import org.junit.Test;
-
-public class BlockStmtTest {
-    @Test
-    public void issue748AddingIdenticalStatementsDoesParentingRight() {
-        BlockStmt blockStmt = new BlockStmt();
-        Expression exp = new NameExpr("x");
-        MethodCallExpr expression = new MethodCallExpr(exp, "y");
-
-        blockStmt.addStatement(expression);
-        blockStmt.addStatement(expression.clone());
-        // This fails when the issue exists:
-        String s = blockStmt.toString();
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/IfElseStmtTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/IfElseStmtTest.java
deleted file mode 100644
index 5775bd0..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/IfElseStmtTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.github.javaparser.ast.stmt;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.expr.NameExpr;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class IfElseStmtTest {
-
-    @Test
-    public void issue1247withElseSingleStmt() {
-        IfStmt ifStmt = (IfStmt) JavaParser.parseStatement("if (cond) doSomething(); else doSomethingElse();");
-        assertEquals(false, ifStmt.hasElseBlock());
-        assertEquals(true, ifStmt.hasElseBranch());
-        assertEquals(false, ifStmt.hasCascadingIfStmt());
-    }
-
-    @Test
-    public void issue1247withElseBlockStmt() {
-        IfStmt ifStmt = (IfStmt) JavaParser.parseStatement("if (cond) doSomething(); else { doSomethingElse(); }");
-        assertEquals(true, ifStmt.hasElseBlock());
-        assertEquals(true, ifStmt.hasElseBranch());
-        assertEquals(false, ifStmt.hasCascadingIfStmt());
-    }
-
-    @Test
-    public void issue1247withElseSingleStmtWhichIsAnIf() {
-        IfStmt ifStmt = (IfStmt) JavaParser.parseStatement("if (cond1) doSomething(); else if (cond2) doSomethingElse();");
-        assertEquals(false, ifStmt.hasElseBlock());
-        assertEquals(true, ifStmt.hasElseBranch());
-        assertEquals(true, ifStmt.hasCascadingIfStmt());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/TryStmtTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/TryStmtTest.java
deleted file mode 100644
index 1a63b21..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/stmt/TryStmtTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.github.javaparser.ast.stmt;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParseStart;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.ast.expr.FieldAccessExpr;
-import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.validator.Java9Validator;
-import org.junit.Test;
-
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
-import static org.junit.Assert.assertTrue;
-
-public class TryStmtTest {
-    @Test
-    public void simpleTest() {
-        TryStmt tryStmt = parse9("try(Reader x = new FileReader()){}");
-        assertInstanceOf(VariableDeclarationExpr.class, tryStmt.getResources().get(0));
-    }
-
-    @Test
-    public void multipleTest() {
-        TryStmt tryStmt = parse9("try(Reader x = new FileReader(); Reader x = new FileReader()){}");
-        assertInstanceOf(VariableDeclarationExpr.class, tryStmt.getResources().get(0));
-
-    }
-
-    @Test
-    public void modifiersTest() {
-        TryStmt tryStmt = parse9("try(final @A Reader x = new FileReader()){}");
-        assertInstanceOf(VariableDeclarationExpr.class, tryStmt.getResources().get(0));
-
-    }
-
-    @Test
-    public void simpleVariable() {
-        TryStmt tryStmt = parse9("try(a){}");
-        assertInstanceOf(NameExpr.class, tryStmt.getResources().get(0));
-
-    }
-
-    @Test
-    public void twoSimpleVariables() {
-        TryStmt tryStmt = parse9("try(a;b){}");
-        assertInstanceOf(NameExpr.class, tryStmt.getResources().get(0));
-        assertInstanceOf(NameExpr.class, tryStmt.getResources().get(1));
-
-    }
-
-    @Test
-    public void complexVariable() {
-        TryStmt tryStmt = parse9("try(a.b.c){}");
-        assertInstanceOf(FieldAccessExpr.class, tryStmt.getResources().get(0));
-
-    }
-
-    @Test
-    public void superAccess() {
-        TryStmt tryStmt = parse9("try(super.a){}");
-        assertInstanceOf(FieldAccessExpr.class, tryStmt.getResources().get(0));
-
-    }
-
-    @Test
-    public void outerClassAccess() {
-        TryStmt tryStmt = parse9("try(X.this.a){}");
-        assertInstanceOf(FieldAccessExpr.class, tryStmt.getResources().get(0));
-
-    }
-
-    private <T> T parse9(String code) {
-        JavaParser parser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
-        ParseResult<Statement> result = parser.parse(ParseStart.STATEMENT, provider(code));
-        assertTrue(result.toString(), result.isSuccessful());
-        return (T) result.getResult().get();
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/type/ArrayTypeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/type/ArrayTypeTest.java
deleted file mode 100644
index 3fdee8e..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/type/ArrayTypeTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.expr.ArrayCreationExpr;
-import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.printer.ConcreteSyntaxModel;
-import org.assertj.core.api.Assertions;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.*;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.assertj.core.api.Assertions.*;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-
-public class ArrayTypeTest {
-    @Test
-    public void getFieldDeclarationWithArrays() {
-        FieldDeclaration fieldDeclaration = parseBodyDeclaration("@C int @A[] @B[] a @X[] @Y[];").asFieldDeclaration();
-
-        ArrayType arrayType1 = fieldDeclaration.getVariable(0).getType().asArrayType();
-        ArrayType arrayType2 = arrayType1.getComponentType().asArrayType();
-        ArrayType arrayType3 = arrayType2.getComponentType().asArrayType();
-        ArrayType arrayType4 = arrayType3.getComponentType().asArrayType();
-        PrimitiveType elementType = arrayType4.getComponentType().asPrimitiveType();
-
-        assertThat(arrayType1.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
-        assertThat(arrayType2.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
-        assertThat(arrayType3.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("X")));
-        assertThat(arrayType4.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("Y")));
-
-        assertThat(elementType.getType()).isEqualTo(PrimitiveType.Primitive.INT);
-        assertThat(fieldDeclaration.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
-
-        assertThat(arrayType1.getParentNode().get().getParentNode().get()).isSameAs(fieldDeclaration);
-    }
-
-    @Test
-    public void getVariableDeclarationWithArrays() {
-        ExpressionStmt variableDeclarationStatement = parseStatement("@C int @A[] @B[] a @X[] @Y[];").asExpressionStmt();
-        VariableDeclarationExpr variableDeclarationExpr = variableDeclarationStatement.getExpression().asVariableDeclarationExpr();
-
-        ArrayType arrayType1 = variableDeclarationExpr.getVariable(0).getType().asArrayType();
-        ArrayType arrayType2 = arrayType1.getComponentType().asArrayType();
-        ArrayType arrayType3 = arrayType2.getComponentType().asArrayType();
-        ArrayType arrayType4 = arrayType3.getComponentType().asArrayType();
-        PrimitiveType elementType = arrayType4.getComponentType().asPrimitiveType();
-
-        assertThat(arrayType1.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
-        assertThat(arrayType2.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
-        assertThat(arrayType3.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("X")));
-        assertThat(arrayType4.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("Y")));
-
-        assertThat(elementType.getType()).isEqualTo(PrimitiveType.Primitive.INT);
-        assertThat(variableDeclarationExpr.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
-
-        assertThat(arrayType1.getParentNode().get().getParentNode().get()).isSameAs(variableDeclarationExpr);
-    }
-
-    @Test
-    public void getMethodDeclarationWithArrays() {
-        MethodDeclaration methodDeclaration = parseBodyDeclaration("@C int @A[] a() @B[] {}").asMethodDeclaration();
-
-        ArrayType arrayType1 = methodDeclaration.getType().asArrayType();
-        ArrayType arrayType2 = arrayType1.getComponentType().asArrayType();
-        Type elementType = arrayType2.getComponentType();
-        assertThat(elementType).isInstanceOf(PrimitiveType.class);
-
-        assertThat(arrayType1.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
-        assertThat(arrayType2.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
-        assertThat(methodDeclaration.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
-
-        assertThat(methodDeclaration.getType().getParentNode().get()).isSameAs(methodDeclaration);
-    }
-
-    @Test
-    public void getParameterWithArrays() {
-        MethodDeclaration methodDeclaration = parseBodyDeclaration("void a(@C int @A[] a @B[]) {}").asMethodDeclaration();
-
-        Parameter parameter = methodDeclaration.getParameter(0);
-
-        ArrayType outerArrayType = parameter.getType().asArrayType();
-
-        ArrayType innerArrayType = outerArrayType.getComponentType().asArrayType();
-        PrimitiveType elementType = innerArrayType.getComponentType().asPrimitiveType();
-
-        assertThat(elementType).isInstanceOf(PrimitiveType.class);
-        assertThat(outerArrayType.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("A")));
-        assertThat(innerArrayType.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("B")));
-        assertThat(parameter.getAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("C")));
-
-        assertThat(parameter.getType().getParentNode().get()).isSameAs(parameter);
-    }
-
-    @Test
-    public void setVariableDeclarationWithArrays() {
-        ExpressionStmt variableDeclarationStatement = parseStatement("@C int @A[] @B[] a @X[] @Y[];").asExpressionStmt();
-        VariableDeclarationExpr variableDeclarationExpr = variableDeclarationStatement.getExpression().asVariableDeclarationExpr();
-
-        variableDeclarationExpr.getVariable(0).setType(new ArrayType(new ArrayType(PrimitiveType.intType())));
-        assertEquals("@C int[][] a;", variableDeclarationStatement.toString());
-    }
-
-    @Test
-    public void setFieldDeclarationWithArrays() {
-        FieldDeclaration fieldDeclaration = parseBodyDeclaration("int[][] a[][];").asFieldDeclaration();
-        fieldDeclaration.getVariable(0).setType(new ArrayType(new ArrayType(parseClassOrInterfaceType("Blob"))));
-
-        assertEquals("Blob[][] a;", fieldDeclaration.toString());
-    }
-
-    @Test
-    public void setMethodDeclarationWithArrays() {
-        MethodDeclaration method = parseBodyDeclaration("int[][] a()[][] {}").asMethodDeclaration();
-        method.setType(new ArrayType(new ArrayType(parseClassOrInterfaceType("Blob"))));
-
-        assertEquals("Blob[][] a() {" + EOL + "}", method.toString());
-    }
-
-    @Test
-    public void fieldDeclarationWithArraysHasCorrectOrigins() {
-        FieldDeclaration fieldDeclaration = parseBodyDeclaration("int[] a[];").asFieldDeclaration();
-
-        Type outerType = fieldDeclaration.getVariables().get(0).getType();
-        assertEquals(ArrayType.Origin.TYPE, outerType.asArrayType().getOrigin());
-        assertEquals(ArrayType.Origin.NAME, outerType.asArrayType().getComponentType().asArrayType().getOrigin());
-    }
-
-    @Test
-    public void methodDeclarationWithArraysHasCorrectOrigins() {
-        MethodDeclaration method = (MethodDeclaration) parseBodyDeclaration("int[] a()[] {}");
-
-        Type outerType = method.getType();
-        assertEquals(ArrayType.Origin.TYPE, outerType.asArrayType().getOrigin());
-        assertEquals(ArrayType.Origin.NAME, outerType.asArrayType().getComponentType().asArrayType().getOrigin());
-    }
-
-    @Test
-    public void setParameterWithArrays() {
-        MethodDeclaration method = parseBodyDeclaration("void a(int[][] a[][]) {}").asMethodDeclaration();
-        method.getParameter(0).setType(new ArrayType(new ArrayType(parseClassOrInterfaceType("Blob"))));
-
-        assertEquals("void a(Blob[][] a) {" + EOL + "}", method.toString());
-    }
-
-    @Test
-    public void getArrayCreationType() {
-        ArrayCreationExpr expr = parseExpression("new int[]");
-        ArrayType outerType = expr.createdType().asArrayType();
-        Type innerType = outerType.getComponentType();
-        assertThat(innerType).isEqualTo(expr.getElementType());
-    }
-    
-    @Test
-    public void ellipsisCanHaveAnnotationsToo() {
-        Parameter p = parseParameter("int[]@X...a[]");
-
-        assertThat(p.getVarArgsAnnotations()).containsExactly(new MarkerAnnotationExpr(parseName("X")));
-        assertEquals("int[][]@X ... a", p.toString());
-        assertEquals("int[][]@X... a", ConcreteSyntaxModel.genericPrettyPrint(p));
-    }
-}
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
deleted file mode 100644
index 17244f3..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/type/TypeTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.github.javaparser.ast.type;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseProblemException;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.validator.Java5Validator;
-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.*;
-
-public class TypeTest {
-    @Test
-    public void asString() {
-        assertEquals("int", typeAsString("int x"));
-        assertEquals("List<Long>", typeAsString("List<Long> x"));
-        assertEquals("String", typeAsString("@A String x"));
-        assertEquals("List<? extends Object>", typeAsString("List<? extends Object> x"));
-    }
-
-    @Test(expected = ParseProblemException.class)
-    public void primitiveTypeArgumentDefaultValidator() {
-        typeAsString("List<long> x;");
-    }
-
-    @Test
-    public void primitiveTypeArgumentLenientValidator() {
-        ParserConfiguration config = new ParserConfiguration()
-                .setLanguageLevel(RAW);
-        config.getPostProcessors().add(new Java5Validator() {{
-            remove(noPrimitiveGenericArguments);
-        }}.postProcessor());
-
-        ParseResult<VariableDeclarationExpr> result = new JavaParser(config).parse(
-                VARIABLE_DECLARATION_EXPR, provider("List<long> x"));
-        assertTrue(result.isSuccessful());
-
-        VariableDeclarationExpr decl = result.getResult().get();
-        assertEquals("List<long>", decl.getVariable(0).getType().asString());
-    }
-
-    private String typeAsString(String s) {
-        return parseVariableDeclarationExpr(s).getVariable(0).getType().asString();
-    }
-
-    @Test
-    public void arrayType() {
-        Type type = parseType("int[]");
-        assertTrue(type.isArrayType());
-        ArrayType arrayType = type.asArrayType();
-        final ArrayType[] s = new ArrayType[1];
-        type.ifArrayType(t -> s[0] = t);
-        assertNotNull(s[0]);
-    }
-
-    @Test
-    public void issue1251() {
-        final Type type = parseType("TypeUtilsTest<String>.Tester");
-        assertEquals("TypeUtilsTest<String>.Tester", type.toString());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java10ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java10ValidatorTest.java
deleted file mode 100644
index 8c2b935..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java10ValidatorTest.java
+++ /dev/null
@@ -1,108 +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.body.BodyDeclaration;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.CLASS_BODY;
-import static com.github.javaparser.ParseStart.STATEMENT;
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_10;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java10ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_10));
-
-    @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);
-    }
-
-    @Test
-    public void varNotAllowedInCast() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int a = (var)20;"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void varNotAllowedInTryWithResources() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(var f = new FileReader(\"\")){ }catch (Exception e){ }"));
-        assertProblems(result, "(line 1,col 5) \"var\" is not allowed here.");
-    }
-
-    @Test
-    public void varNotAllowedInField() {
-        ParseResult<BodyDeclaration<?>> result = javaParser.parse(CLASS_BODY, provider("var a = 20;"));
-        assertProblems(result, "(line 1,col 1) \"var\" is not allowed here.");
-    }
-
-    @Test
-    public void varNotAllowedInTypeArguments() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("new X<var>();"));
-        assertProblems(result, "(line 1,col 7) \"var\" is not allowed here.");
-    }
-
-    @Test
-    public void varNotAllowedInLambdaParameters() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("x((var x) -> null);"));
-        assertProblems(result, "(line 1,col 4) \"var\" is not allowed here.");
-    }
-
-    @Test
-    public void emptyInitializerNotAllowed() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a;"));
-        assertProblems(result, "(line 1,col 1) \"var\" needs an initializer.");
-    }
-
-    @Test
-    public void multipleVariablesNotAllowed() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=1, b=2;"));
-        assertProblems(result, "(line 1,col 1) \"var\" only takes a single variable.");
-    }
-
-    @Test
-    public void nullVariablesNotAllowed() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=null;"));
-        assertProblems(result, "(line 1,col 1) \"var\" cannot infer type from just null.");
-    }
-
-    @Test
-    public void arrayDimensionBracketsNotAllowed() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=new String[]{};"));
-        assertProblems(result, "(line 1,col 1) \"var\" cannot infer array types.");
-    }
-
-    // This is pretty hard to impossible to implement correctly with just the AST.
-    @Ignore
-    @Test
-    public void selfReferenceNotAllowed() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=a;"));
-        assertProblems(result, "");
-    }
-
-    // Can be implemented once https://github.com/javaparser/javaparser/issues/1434 is implemented.
-    @Ignore
-    @Test
-    public void polyExpressionAsInitializerNotAllowed() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("var a=new ArrayList<>();"));
-        assertProblems(result, "");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java11ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java11ValidatorTest.java
deleted file mode 100644
index 1e1f8c0..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java11ValidatorTest.java
+++ /dev/null
@@ -1,22 +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.ParserConfiguration.LanguageLevel.JAVA_11_PREVIEW;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertNoProblems;
-
-public class Java11ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_11_PREVIEW));
-
-    @Test
-    public void varAllowedInLocalVariableDeclaration() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("x((var x, var y) -> x+y);"));
-        assertNoProblems(result);
-    }
-}
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
deleted file mode 100644
index 7160bcf..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_0ValidatorTest.java
+++ /dev/null
@@ -1,98 +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.Problem;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.ArrayCreationExpr;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.ast.type.PrimitiveType;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.github.javaparser.ParseStart.*;
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-import static org.junit.Assert.assertEquals;
-
-public class Java1_0ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_0));
-
-    @Test
-    public void tryWithoutResources() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(X x=new Y()){}"));
-        assertProblems(result,
-                "(line 1,col 1) Catch with resource is not supported.",
-                "(line 1,col 1) Try has no finally and no catch.");
-    }
-
-    @Test
-    public void classExtendingMoreThanOne() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X extends Y, Z {}"));
-        assertProblems(result, "(line 1,col 20) A class cannot extend more than one other class.");
-    }
-
-    @Test
-    public void interfaceUsingImplements() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X implements Y {}"));
-        assertProblems(result, "(line 1,col 24) An interface cannot implement other interfaces.");
-    }
-
-    @Test
-    public void interfaceWithInitializer() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X {{}}"));
-        assertProblems(result, "(line 1,col 14) An interface cannot have initializers.");
-    }
-
-    @Test
-    public void defaultInClass() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X {default void a(){};}"));
-        assertProblems(result, "(line 1,col 10) 'default' is not allowed here.");
-    }
-
-    @Test
-    public void leftHandAssignmentCannotBeAConditional() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("(1==2)=3"));
-        assertProblems(result, "(line 1,col 1) Illegal left hand side of an assignment.");
-    }
-
-    @Test
-    public void leftHandAssignmentCannotBeEmptyBraces() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("()=3"));
-        assertProblems(result,
-                "(line 1,col 1) Illegal left hand side of an assignment.",
-                "(line 1,col 1) Lambdas are not supported.");
-    }
-
-    @Test
-    public void leftHandAssignmentCanBeInBraces() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("(i) += (i) += 1"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void noInnerClasses() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{class Y{}}"));
-        assertProblems(result, "(line 1,col 9) inner classes or interfaces are not supported.");
-    }
-
-    @Test
-    public void noReflection() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("Abc.class"));
-        assertProblems(result, "(line 1,col 1) Reflection is not supported.");
-    }
-
-    @Test
-    public void nonEmptyList() {
-        ArrayCreationExpr expr = new ArrayCreationExpr(PrimitiveType.booleanType());
-        List<Problem> problems= new ArrayList<>();
-        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/Java1_1ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_1ValidatorTest.java
deleted file mode 100644
index 6331d9a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_1ValidatorTest.java
+++ /dev/null
@@ -1,292 +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.CompilationUnit;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-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.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java1_1ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_1));
-
-    public static final String allModifiers = "public protected private abstract static final transient volatile synchronized native strictfp transitive default ";
-
-    @Test
-    public void topClass() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "class X{}"));
-        assertProblems(result,
-                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 1) 'transient' is not allowed here.",
-                "(line 1,col 1) 'default' is not allowed here.",
-                "(line 1,col 1) 'volatile' is not allowed here.",
-                "(line 1,col 1) 'strictfp' is not allowed here.",
-                "(line 1,col 1) 'private' is not allowed here.",
-                "(line 1,col 1) 'protected' is not allowed here.",
-                "(line 1,col 1) 'synchronized' is not allowed here.",
-                "(line 1,col 1) 'native' is not allowed here.",
-                "(line 1,col 1) 'transitive' is not allowed here.",
-                "(line 1,col 1) 'static' is not allowed here."
-        );
-    }
-
-    @Test
-    public void nestedClass() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "class I{}}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void localClass() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{ void x() {" + allModifiers + "class I{}}}"));
-        assertProblems(result,
-                "(line 1,col 20) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 20) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 20) 'transient' is not allowed here.",
-                "(line 1,col 20) 'volatile' is not allowed here.",
-                "(line 1,col 20) 'default' is not allowed here.",
-                "(line 1,col 20) 'synchronized' is not allowed here.",
-                "(line 1,col 20) 'native' is not allowed here.",
-                "(line 1,col 20) 'transitive' is not allowed here.",
-                "(line 1,col 20) 'strictfp' is not allowed here.",
-                "(line 1,col 20) 'static' is not allowed here.",
-                "(line 1,col 20) 'public' is not allowed here.",
-                "(line 1,col 20) 'private' is not allowed here.",
-                "(line 1,col 20) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void topInterface() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "interface X{}"));
-        assertProblems(result,
-                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 1) 'transient' is not allowed here.",
-                "(line 1,col 1) 'volatile' is not allowed here.",
-                "(line 1,col 1) 'default' is not allowed here.",
-                "(line 1,col 1) 'strictfp' is not allowed here.",
-                "(line 1,col 1) 'synchronized' is not allowed here.",
-                "(line 1,col 1) 'native' is not allowed here.",
-                "(line 1,col 1) 'transitive' is not allowed here.",
-                "(line 1,col 1) 'static' is not allowed here.",
-                "(line 1,col 1) 'final' is not allowed here.",
-                "(line 1,col 1) 'private' is not allowed here.",
-                "(line 1,col 1) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void nestedInterface() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "interface I{}}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'final' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void constructor() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "X(){};}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'final' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'abstract' is not allowed here.",
-                "(line 1,col 9) 'static' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void constructorParameter() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{X(" + allModifiers + " int i){};}"));
-        assertProblems(result,
-                "(line 1,col 11) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 11) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 11) 'transient' is not allowed here.",
-                "(line 1,col 11) 'volatile' is not allowed here.",
-                "(line 1,col 11) 'synchronized' is not allowed here.",
-                "(line 1,col 11) 'native' is not allowed here.",
-                "(line 1,col 11) 'strictfp' is not allowed here.",
-                "(line 1,col 11) 'default' is not allowed here.",
-                "(line 1,col 11) 'abstract' is not allowed here.",
-                "(line 1,col 11) 'static' is not allowed here.",
-                "(line 1,col 11) 'transitive' is not allowed here.",
-                "(line 1,col 11) 'private' is not allowed here.",
-                "(line 1,col 11) 'public' is not allowed here.",
-                "(line 1,col 11) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void classMethod() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int x(){};}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void interfaceMethod() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
-        assertProblems(result,
-                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
-                "(line 1,col 13) 'transient' is not allowed here.",
-                "(line 1,col 13) 'strictfp' is not allowed here.",
-                "(line 1,col 13) 'volatile' is not allowed here.",
-                "(line 1,col 13) 'default' is not allowed here.",
-                "(line 1,col 13) 'transitive' is not allowed here.",
-                "(line 1,col 13) 'private' is not allowed here.",
-                "(line 1,col 13) 'static' is not allowed here."
-        );
-    }
-
-    @Test
-    public void methodParameter() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(" + allModifiers + " int i){};}"));
-        assertProblems(result,
-                "(line 1,col 15) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 15) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 15) 'transient' is not allowed here.",
-                "(line 1,col 15) 'volatile' is not allowed here.",
-                "(line 1,col 15) 'synchronized' is not allowed here.",
-                "(line 1,col 15) 'native' is not allowed here.",
-                "(line 1,col 15) 'strictfp' is not allowed here.",
-                "(line 1,col 15) 'abstract' is not allowed here.",
-                "(line 1,col 15) 'default' is not allowed here.",
-                "(line 1,col 15) 'static' is not allowed here.",
-                "(line 1,col 15) 'transitive' is not allowed here.",
-                "(line 1,col 15) 'private' is not allowed here.",
-                "(line 1,col 15) 'public' is not allowed here.",
-                "(line 1,col 15) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void field() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int i;}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'abstract' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void localVariable() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){" + allModifiers + "int i;}}"));
-        assertProblems(result,
-                "(line 1,col 17) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 17) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 17) 'transient' is not allowed here.",
-                "(line 1,col 17) 'volatile' is not allowed here.",
-                "(line 1,col 17) 'synchronized' is not allowed here.",
-                "(line 1,col 17) 'native' is not allowed here.",
-                "(line 1,col 17) 'default' is not allowed here.",
-                "(line 1,col 17) 'strictfp' is not allowed here.",
-                "(line 1,col 17) 'abstract' is not allowed here.",
-                "(line 1,col 17) 'static' is not allowed here.",
-                "(line 1,col 17) 'transitive' is not allowed here.",
-                "(line 1,col 17) 'private' is not allowed here.",
-                "(line 1,col 17) 'public' is not allowed here.",
-                "(line 1,col 17) 'protected' is not allowed here."
-        );
-    }
-
-
-    @Test
-    public void catchParameter() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){ try{}catch(" + allModifiers + " Integer x){}}}"));
-        assertProblems(result,
-                "(line 1,col 144) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 144) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 144) 'transient' is not allowed here.",
-                "(line 1,col 144) 'volatile' is not allowed here.",
-                "(line 1,col 144) 'synchronized' is not allowed here.",
-                "(line 1,col 144) 'native' is not allowed here.",
-                "(line 1,col 144) 'default' is not allowed here.",
-                "(line 1,col 144) 'strictfp' is not allowed here.",
-                "(line 1,col 144) 'abstract' is not allowed here.",
-                "(line 1,col 144) 'static' is not allowed here.",
-                "(line 1,col 144) 'transitive' is not allowed here.",
-                "(line 1,col 144) 'private' is not allowed here.",
-                "(line 1,col 144) 'public' is not allowed here.",
-                "(line 1,col 144) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void innerClasses() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{class Y{}}"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void localInterface() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{ void x() {" + allModifiers + "interface I{}}}"));
-        assertProblems(result, "(line 1,col 20) There is no such thing as a local interface."
-        );
-    }
-
-    @Test
-    public void reflection() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("Abc.class"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void strictfpAllowedAsIdentifier() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int strictfp;"));
-        assertNoProblems(result);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_2ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_2ValidatorTest.java
deleted file mode 100644
index 3ae7018..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_2ValidatorTest.java
+++ /dev/null
@@ -1,275 +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.CompilationUnit;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-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.assertProblems;
-
-public class Java1_2ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_2));
-
-    private final String allModifiers = "public protected private abstract static final transient volatile synchronized native strictfp transitive default ";
-
-    @Test
-    public void topClass() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "class X{}"));
-        assertProblems(result,
-                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 1) 'transient' is not allowed here.",
-                "(line 1,col 1) 'default' is not allowed here.",
-                "(line 1,col 1) 'volatile' is not allowed here.",
-                "(line 1,col 1) 'private' is not allowed here.",
-                "(line 1,col 1) 'protected' is not allowed here.",
-                "(line 1,col 1) 'synchronized' is not allowed here.",
-                "(line 1,col 1) 'native' is not allowed here.",
-                "(line 1,col 1) 'transitive' is not allowed here.",
-                "(line 1,col 1) 'static' is not allowed here."
-        );
-    }
-
-    @Test
-    public void nestedClass() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "class I{}}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void localClass() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{ void x() {" + allModifiers + "class I{}}}"));
-        assertProblems(result,
-                "(line 1,col 20) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 20) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 20) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 20) 'transient' is not allowed here.",
-                "(line 1,col 20) 'volatile' is not allowed here.",
-                "(line 1,col 20) 'default' is not allowed here.",
-                "(line 1,col 20) 'synchronized' is not allowed here.",
-                "(line 1,col 20) 'native' is not allowed here.",
-                "(line 1,col 20) 'transitive' is not allowed here.",
-                "(line 1,col 20) 'static' is not allowed here.",
-                "(line 1,col 20) 'public' is not allowed here.",
-                "(line 1,col 20) 'private' is not allowed here.",
-                "(line 1,col 20) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void topInterface() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "interface X{}"));
-        assertProblems(result,
-                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 1) 'transient' is not allowed here.",
-                "(line 1,col 1) 'volatile' is not allowed here.",
-                "(line 1,col 1) 'default' is not allowed here.",
-                "(line 1,col 1) 'synchronized' is not allowed here.",
-                "(line 1,col 1) 'native' is not allowed here.",
-                "(line 1,col 1) 'transitive' is not allowed here.",
-                "(line 1,col 1) 'static' is not allowed here.",
-                "(line 1,col 1) 'final' is not allowed here.",
-                "(line 1,col 1) 'private' is not allowed here.",
-                "(line 1,col 1) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void nestedInterface() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "interface I{}}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'final' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void constructor() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "X(){};}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'final' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'abstract' is not allowed here.",
-                "(line 1,col 9) 'static' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void constructorParameter() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{X(" + allModifiers + " int i){};}"));
-        assertProblems(result,
-                "(line 1,col 11) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 11) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 11) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 11) 'transient' is not allowed here.",
-                "(line 1,col 11) 'volatile' is not allowed here.",
-                "(line 1,col 11) 'synchronized' is not allowed here.",
-                "(line 1,col 11) 'native' is not allowed here.",
-                "(line 1,col 11) 'strictfp' is not allowed here.",
-                "(line 1,col 11) 'default' is not allowed here.",
-                "(line 1,col 11) 'abstract' is not allowed here.",
-                "(line 1,col 11) 'static' is not allowed here.",
-                "(line 1,col 11) 'transitive' is not allowed here.",
-                "(line 1,col 11) 'private' is not allowed here.",
-                "(line 1,col 11) 'public' is not allowed here.",
-                "(line 1,col 11) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void classMethod() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int x(){};}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 9) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void interfaceMethod() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
-        assertProblems(result,
-                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 13) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
-                "(line 1,col 13) 'transient' is not allowed here.",
-                "(line 1,col 13) 'volatile' is not allowed here.",
-                "(line 1,col 13) 'default' is not allowed here.",
-                "(line 1,col 13) 'transitive' is not allowed here.",
-                "(line 1,col 13) 'private' is not allowed here.",
-                "(line 1,col 13) 'static' is not allowed here."
-        );
-    }
-
-    @Test
-    public void methodParameter() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(" + allModifiers + " int i){};}"));
-        assertProblems(result,
-                "(line 1,col 15) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 15) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 15) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 15) 'transient' is not allowed here.",
-                "(line 1,col 15) 'volatile' is not allowed here.",
-                "(line 1,col 15) 'synchronized' is not allowed here.",
-                "(line 1,col 15) 'native' is not allowed here.",
-                "(line 1,col 15) 'strictfp' is not allowed here.",
-                "(line 1,col 15) 'abstract' is not allowed here.",
-                "(line 1,col 15) 'default' is not allowed here.",
-                "(line 1,col 15) 'static' is not allowed here.",
-                "(line 1,col 15) 'transitive' is not allowed here.",
-                "(line 1,col 15) 'private' is not allowed here.",
-                "(line 1,col 15) 'public' is not allowed here.",
-                "(line 1,col 15) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void field() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "int i;}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'strictfp' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'abstract' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void localVariable() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){" + allModifiers + "int i;}}"));
-        assertProblems(result,
-                "(line 1,col 17) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 17) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 17) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 17) 'transient' is not allowed here.",
-                "(line 1,col 17) 'volatile' is not allowed here.",
-                "(line 1,col 17) 'synchronized' is not allowed here.",
-                "(line 1,col 17) 'native' is not allowed here.",
-                "(line 1,col 17) 'default' is not allowed here.",
-                "(line 1,col 17) 'strictfp' is not allowed here.",
-                "(line 1,col 17) 'abstract' is not allowed here.",
-                "(line 1,col 17) 'static' is not allowed here.",
-                "(line 1,col 17) 'transitive' is not allowed here.",
-                "(line 1,col 17) 'private' is not allowed here.",
-                "(line 1,col 17) 'public' is not allowed here.",
-                "(line 1,col 17) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void catchParameter() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){ try{}catch(" + allModifiers + " Integer x){}}}"));
-        assertProblems(result,
-                "(line 1,col 144) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 144) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 144) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 144) 'transient' is not allowed here.",
-                "(line 1,col 144) 'volatile' is not allowed here.",
-                "(line 1,col 144) 'synchronized' is not allowed here.",
-                "(line 1,col 144) 'native' is not allowed here.",
-                "(line 1,col 144) 'default' is not allowed here.",
-                "(line 1,col 144) 'strictfp' is not allowed here.",
-                "(line 1,col 144) 'abstract' is not allowed here.",
-                "(line 1,col 144) 'static' is not allowed here.",
-                "(line 1,col 144) 'transitive' is not allowed here.",
-                "(line 1,col 144) 'private' is not allowed here.",
-                "(line 1,col 144) 'public' is not allowed here.",
-                "(line 1,col 144) 'protected' is not allowed here."
-        );
-    }
-    
-    @Test
-    public void strictfpNotAllowedAsIdentifier() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int strictfp;"));
-        assertProblems(result, "(line 1,col 5) 'strictfp' cannot be used as an identifier as it is a keyword.");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_3ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_3ValidatorTest.java
deleted file mode 100644
index b10114a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_3ValidatorTest.java
+++ /dev/null
@@ -1,22 +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.ParserConfiguration.LanguageLevel.*;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java1_3ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_3));
-
-    @Test
-    public void noAssert() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("assert a;"));
-        assertProblems(result, "(line 1,col 1) 'assert' keyword is not supported.");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_4ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_4ValidatorTest.java
deleted file mode 100644
index ed0be99..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java1_4ValidatorTest.java
+++ /dev/null
@@ -1,70 +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.CompilationUnit;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.*;
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.TestUtils.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java1_4ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_1_4));
-
-    @Test
-    public void yesAssert() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("assert a;"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void noGenerics() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X<A>{List<String> b;}"));
-        assertProblems(result,
-                "(line 1,col 12) Generics are not supported.",
-                "(line 1,col 1) Generics are not supported."
-        );
-    }
-
-    @Test
-    public void noAnnotations() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("@Abc @Def() @Ghi(a=3) @interface X{}"));
-        assertProblems(result,
-                "(line 1,col 6) Annotations are not supported.",
-                "(line 1,col 13) Annotations are not supported.",
-                "(line 1,col 1) Annotations are not supported."
-        );
-    }
-
-    @Test
-    public void novarargs() {
-        ParseResult<Parameter> result = javaParser.parse(PARAMETER, provider("String... x"));
-        assertProblems(result, "(line 1,col 1) Varargs are not supported.");
-    }
-
-    @Test
-    public void noforeach() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(X x: xs){}"));
-        assertProblems(result, "(line 1,col 1) For-each loops are not supported.");
-    }
-
-    @Test
-    public void staticImport() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("import static x;import static x.*;import x.X;import x.*;"));
-        assertProblems(result,
-                "(line 1,col 17) Static imports are not supported.",
-                "(line 1,col 1) Static imports are not supported.");
-    }
-
-    @Test
-    public void enumAllowedAsIdentifier() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int enum;"));
-        assertNoProblems(result);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java5ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java5ValidatorTest.java
deleted file mode 100644
index 315167f..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java5ValidatorTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package com.github.javaparser.ast.validator;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParseStart;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.*;
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.ast.validator.Java1_1ValidatorTest.allModifiers;
-import static com.github.javaparser.utils.TestUtils.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java5ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_5));
-
-    @Test
-    public void genericsWithoutDiamond() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X<A>{List<String> b = new ArrayList<>();}"));
-        assertProblems(result, "(line 1,col 33) The diamond operator is not supported.");
-    }
-
-    @Test
-    public void topAnnotationDeclaration() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "@interface X{}"));
-        assertProblems(result,
-                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 1) 'transient' is not allowed here.",
-                "(line 1,col 1) 'volatile' is not allowed here.",
-                "(line 1,col 1) 'synchronized' is not allowed here.",
-                "(line 1,col 1) 'default' is not allowed here.",
-                "(line 1,col 1) 'native' is not allowed here.",
-                "(line 1,col 1) 'transitive' is not allowed here.",
-                "(line 1,col 1) 'static' is not allowed here.",
-                "(line 1,col 1) 'final' is not allowed here.",
-                "(line 1,col 1) 'private' is not allowed here.",
-                "(line 1,col 1) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void nestedAnnotationDeclaration() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "@interface I{}}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'final' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void annotationMember() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("@interface X{" + allModifiers + "int x();}"));
-        assertProblems(result,
-                "(line 1,col 14) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 14) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 14) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 14) 'transient' is not allowed here.",
-                "(line 1,col 14) 'volatile' is not allowed here.",
-                "(line 1,col 14) 'final' is not allowed here.",
-                "(line 1,col 14) 'synchronized' is not allowed here.",
-                "(line 1,col 14) 'default' is not allowed here.",
-                "(line 1,col 14) 'native' is not allowed here.",
-                "(line 1,col 14) 'protected' is not allowed here.",
-                "(line 1,col 14) 'private' is not allowed here.",
-                "(line 1,col 14) 'strictfp' is not allowed here.",
-                "(line 1,col 14) 'static' is not allowed here.",
-                "(line 1,col 14) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void topEnum() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider(allModifiers + "enum X{}"));
-        assertProblems(result,
-                "(line 1,col 1) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 1) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 1) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 1) 'transient' is not allowed here.",
-                "(line 1,col 1) 'volatile' is not allowed here.",
-                "(line 1,col 1) 'synchronized' is not allowed here.",
-                "(line 1,col 1) 'default' is not allowed here.",
-                "(line 1,col 1) 'native' is not allowed here.",
-                "(line 1,col 1) 'transitive' is not allowed here.",
-                "(line 1,col 1) 'static' is not allowed here.",
-                "(line 1,col 1) 'abstract' is not allowed here.",
-                "(line 1,col 1) 'final' is not allowed here.",
-                "(line 1,col 1) 'private' is not allowed here.",
-                "(line 1,col 1) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void nestedEnum() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{" + allModifiers + "enum I{}}"));
-        assertProblems(result,
-                "(line 1,col 9) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 9) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 9) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 9) 'transient' is not allowed here.",
-                "(line 1,col 9) 'volatile' is not allowed here.",
-                "(line 1,col 9) 'default' is not allowed here.",
-                "(line 1,col 9) 'abstract' is not allowed here.",
-                "(line 1,col 9) 'final' is not allowed here.",
-                "(line 1,col 9) 'synchronized' is not allowed here.",
-                "(line 1,col 9) 'native' is not allowed here.",
-                "(line 1,col 9) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void varargs() {
-        ParseResult<Parameter> result = javaParser.parse(PARAMETER, provider("String... x"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void foreach() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("for(X x: xs){}"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void staticImport() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("import static x;import static x.*;import x.X;import x.*;"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void noPrimitiveTypeArguments() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X extends Y<int> {}"));
-        assertProblems(result, "(line 1,col 17) Type arguments may not be primitive.");
-    }
-
-    @Test
-    public void enumAllowedAsIdentifier() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("int enum;"));
-        assertProblems(result, "(line 1,col 5) 'enum' cannot be used as an identifier as it is a keyword.");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java6ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java6ValidatorTest.java
deleted file mode 100644
index d066abe..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java6ValidatorTest.java
+++ /dev/null
@@ -1,42 +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.expr.Expression;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-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.assertProblems;
-
-public class Java6ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_6));
-
-    @Test
-    public void noStringsInSwitch() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case \"abc\": ;}"));
-        assertProblems(result, "(line 1,col 16) Strings in switch statements are not supported.");
-    }
-
-    @Test
-    public void nobinaryIntegerLiterals() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("0b01"));
-        assertProblems(result, "(line 1,col 1) Binary literal values are not supported.");
-    }
-
-    @Test
-    public void noUnderscoresInIntegerLiterals() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("1_000_000"));
-        assertProblems(result, "(line 1,col 1) Underscores in literal values are not supported.");
-    }
-
-    @Test
-    public void noMultiCatch() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try{}catch(Abc|Def e){}"));
-        assertProblems(result, "(line 1,col 12) Multi-catch is not supported.");
-    }
-}
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
deleted file mode 100644
index a2a03f8..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java7ValidatorTest.java
+++ /dev/null
@@ -1,107 +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.Problem;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import com.github.javaparser.ast.type.UnionType;
-import org.junit.Test;
-
-import java.util.*;
-
-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.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java7ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_7));
-
-    @Test
-    public void generics() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X<A>{List<String> b = new ArrayList<>();}"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void defaultMethodWithoutBody() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X {default void a();}"));
-        assertProblems(result, "(line 1,col 14) 'default' is not allowed here.");
-    }
-
-    @Test
-    public void tryWithoutAnything() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try{}"));
-        assertProblems(result, "(line 1,col 1) Try has no finally, no catch, and no resources.");
-    }
-
-    @Test
-    public void tryWithResourceVariableDeclaration() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(Reader r = new Reader()){}"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void tryWithResourceReference() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(a.b.c){}"));
-        assertProblems(result, "(line 1,col 1) Try with resources only supports variable declarations.");
-    }
-
-    @Test
-    public void stringsInSwitch() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("switch(x){case \"abc\": ;}"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void binaryIntegerLiterals() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("0b01"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void underscoresInIntegerLiterals() {
-        ParseResult<Expression> result = javaParser.parse(EXPRESSION, provider("1_000_000"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void multiCatch() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try{}catch(Abc|Def e){}"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void multiCatchWithoutElements() {
-        UnionType unionType = new UnionType();
-
-        List<Problem> problems = new ArrayList<>();
-        new Java7Validator().accept(unionType, new ProblemReporter(problems::add));
-        
-        assertProblems(problems, "UnionType.elements can not be empty.");
-    }
-
-    @Test
-    public void multiCatchWithOneElement() {
-        UnionType unionType = new UnionType();
-        unionType.getElements().add(new ClassOrInterfaceType());
-
-        List<Problem> problems = new ArrayList<>();
-        new Java7Validator().accept(unionType, new ProblemReporter(problems::add));
-        
-        assertProblems(problems, "Union type (multi catch) must have at least two elements.");
-    }
-
-    @Test
-    public void noLambdas() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("a(() -> 1);"));
-        assertProblems(result, "(line 1,col 3) Lambdas are not supported.");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java8ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java8ValidatorTest.java
deleted file mode 100644
index 216fb5b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java8ValidatorTest.java
+++ /dev/null
@@ -1,82 +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.CompilationUnit;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-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.ast.validator.Java1_1ValidatorTest.allModifiers;
-import static com.github.javaparser.utils.TestUtils.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java8ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_8));
-
-    @Test
-    public void localInterface() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X {void a(){interface I{}};}"));
-        assertProblems(result, "(line 1,col 19) There is no such thing as a local interface.");
-    }
-
-    @Test
-    public void lambdaParameter() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("class X{int x(){ a((" + allModifiers + " Integer x) -> 10);}}"));
-        assertProblems(result,
-                "(line 1,col 21) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 21) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 21) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 21) 'transient' is not allowed here.",
-                "(line 1,col 21) 'volatile' is not allowed here.",
-                "(line 1,col 21) 'synchronized' is not allowed here.",
-                "(line 1,col 21) 'strictfp' is not allowed here.",
-                "(line 1,col 21) 'default' is not allowed here.",
-                "(line 1,col 21) 'native' is not allowed here.",
-                "(line 1,col 21) 'strictfp' is not allowed here.",
-                "(line 1,col 21) 'abstract' is not allowed here.",
-                "(line 1,col 21) 'static' is not allowed here.",
-                "(line 1,col 21) 'transitive' is not allowed here.",
-                "(line 1,col 21) 'private' is not allowed here.",
-                "(line 1,col 21) 'public' is not allowed here.",
-                "(line 1,col 21) 'protected' is not allowed here."
-        );
-    }
-
-    @Test
-    public void interfaceMethod() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
-        assertProblems(result,
-                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 13) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
-                "(line 1,col 13) 'transient' is not allowed here.",
-                "(line 1,col 13) 'volatile' is not allowed here.",
-                "(line 1,col 13) 'transitive' is not allowed here.",
-                "(line 1,col 13) 'private' is not allowed here."
-        );
-    }
-
-    @Test
-    public void defaultMethodWithoutBody() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X {default void a();}"));
-        assertProblems(result, "(line 1,col 14) 'default' methods must have a body.");
-    }
-
-    @Test
-    public void lambdas() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("a(() -> 1);"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void noModules() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("open module x {}"));
-        assertProblems(result, "(line 1,col 1) Modules are not supported.");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java9ValidatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java9ValidatorTest.java
deleted file mode 100644
index 911f6a9..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/validator/Java9ValidatorTest.java
+++ /dev/null
@@ -1,79 +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.CompilationUnit;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.Test;
-
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-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.ast.validator.Java1_1ValidatorTest.allModifiers;
-import static com.github.javaparser.utils.TestUtils.assertNoProblems;
-import static com.github.javaparser.utils.TestUtils.assertProblems;
-
-public class Java9ValidatorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
-
-    @Test
-    public void underscoreIdentifiers() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("a.b._.c.d = act(_, _ -> _);"));
-        assertProblems(result,
-                "(line 1,col 5) '_' is a reserved keyword.",
-                "(line 1,col 17) '_' is a reserved keyword.",
-                "(line 1,col 20) '_' is a reserved keyword.",
-                "(line 1,col 25) '_' is a reserved keyword."
-        );
-    }
-
-    @Test
-    public void moduleRequires() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("module x{requires " + allModifiers + " a;}"));
-        assertProblems(result,
-                "(line 1,col 10) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 10) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 10) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 10) 'transient' is not allowed here.",
-                "(line 1,col 10) 'volatile' is not allowed here.",
-                "(line 1,col 10) 'final' is not allowed here.",
-                "(line 1,col 10) 'synchronized' is not allowed here.",
-                "(line 1,col 10) 'default' is not allowed here.",
-                "(line 1,col 10) 'native' is not allowed here.",
-                "(line 1,col 10) 'private' is not allowed here.",
-                "(line 1,col 10) 'protected' is not allowed here.",
-                "(line 1,col 10) 'strictfp' is not allowed here.",
-                "(line 1,col 10) 'abstract' is not allowed here.",
-                "(line 1,col 10) 'public' is not allowed here."
-        );
-    }
-
-    @Test
-    public void interfaceMethod() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("interface X{" + allModifiers + "int x(){};}"));
-        assertProblems(result,
-                "(line 1,col 13) Can have only one of 'public', 'protected', 'private'.",
-                "(line 1,col 13) Can have only one of 'final', 'abstract'.",
-                "(line 1,col 13) Can have only one of 'native', 'strictfp'.",
-                "(line 1,col 13) Cannot be 'abstract' and also 'private', 'static', 'final', 'native', 'strictfp', 'synchronized'.",
-                "(line 1,col 13) 'transient' is not allowed here.",
-                "(line 1,col 13) 'volatile' is not allowed here.",
-                "(line 1,col 13) 'transitive' is not allowed here."
-        );
-    }
-
-    @Test
-    public void modules() {
-        ParseResult<CompilationUnit> result = javaParser.parse(COMPILATION_UNIT, provider("open module x {}"));
-        assertNoProblems(result);
-    }
-
-    @Test
-    public void tryWithResourceReference() {
-        ParseResult<Statement> result = javaParser.parse(STATEMENT, provider("try(a.b.c){}"));
-        assertNoProblems(result);
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/CloneVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/CloneVisitorTest.java
deleted file mode 100644
index e596611..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/CloneVisitorTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.visitor;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.type.Type;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Iterator;
-
-import static com.github.javaparser.JavaParser.*;
-import static org.junit.Assert.assertEquals;
-
-public class CloneVisitorTest {
-    CompilationUnit cu;
-
-    @Before
-    public void setUp() {
-        cu = new CompilationUnit();
-    }
-
-    @After
-    public void teardown() {
-        cu = null;
-    }
-
-    @Test
-    public void cloneJavaDocTest() {
-        NodeList<BodyDeclaration<?>> bodyDeclarationList = new NodeList<>();
-        bodyDeclarationList.add(new AnnotationMemberDeclaration().setJavadocComment("javadoc"));
-        bodyDeclarationList.add(new ConstructorDeclaration().setJavadocComment("javadoc"));
-        bodyDeclarationList.add(new EnumConstantDeclaration().setJavadocComment("javadoc"));
-        bodyDeclarationList.add(new FieldDeclaration().setJavadocComment("javadoc"));
-        bodyDeclarationList.add(new InitializerDeclaration().setJavadocComment("javadoc"));
-        bodyDeclarationList.add(new MethodDeclaration().setJavadocComment("javadoc"));
-
-        NodeList<TypeDeclaration<?>> typeDeclarationList = new NodeList<>();
-        AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration();
-        annotationDeclaration.setName("nnotationDeclarationTest");
-        typeDeclarationList.add(annotationDeclaration.setJavadocComment("javadoc"));
-
-        ClassOrInterfaceDeclaration classOrInterfaceDeclaration2 = new ClassOrInterfaceDeclaration();
-        classOrInterfaceDeclaration2.setName("emptyTypeDeclarationTest");
-        typeDeclarationList.add(classOrInterfaceDeclaration2.setJavadocComment("javadoc"));
-
-        EnumDeclaration enumDeclaration = new EnumDeclaration();
-        enumDeclaration.setName("enumDeclarationTest");
-        typeDeclarationList.add(enumDeclaration.setJavadocComment("javadoc"));
-
-        ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration();
-        classOrInterfaceDeclaration.setName("classOrInterfaceDeclarationTest");
-        typeDeclarationList.add(classOrInterfaceDeclaration.setJavadocComment("javadoc"));
-
-        ClassOrInterfaceDeclaration classOrInterfaceDeclaration1 = new ClassOrInterfaceDeclaration();
-        classOrInterfaceDeclaration1.setName("emptyTypeDeclarationTest1");
-        typeDeclarationList.add(classOrInterfaceDeclaration2.setMembers(bodyDeclarationList));
-
-        cu.setTypes(typeDeclarationList);
-        CompilationUnit cuClone = (CompilationUnit) new CloneVisitor().visit(cu, null);
-
-        NodeList<TypeDeclaration<?>> typeDeclarationListClone = cuClone.getTypes();
-        Iterator<TypeDeclaration<?>> typeItr = typeDeclarationListClone.iterator();
-        TypeDeclaration<?> typeDeclaration;
-        while (typeItr.hasNext()) {
-            typeDeclaration = typeItr.next();
-            if (typeDeclaration.getMembers() == null) {
-                assertEquals(typeDeclaration.getComment().get().getContent(), " javadoc");
-            } else {
-                Iterator<BodyDeclaration<?>> bodyItr = typeDeclaration.getMembers().iterator();
-                while (bodyItr.hasNext()) {
-                    BodyDeclaration<?> bodyDeclaration = bodyItr.next();
-                    assertEquals(bodyDeclaration.getComment().get().getContent(), " javadoc");
-                }
-            }
-        }
-    }
-    
-    @Test
-    public void cloneAnnotationOnWildcardTypeArgument() {
-        Type type = parseType("List<@C ? extends Object>").clone();
-        assertEquals("List<@C ? extends Object>", type.toString());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/HashCodeVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/HashCodeVisitorTest.java
deleted file mode 100644
index 679fb1d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/HashCodeVisitorTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.github.javaparser.ast.visitor;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-public class HashCodeVisitorTest {
-    @Test
-    public void testEquals() {
-        CompilationUnit p1 = JavaParser.parse("class X { }");
-        CompilationUnit p2 = JavaParser.parse("class X { }");
-        assertEquals(p1.hashCode(), p2.hashCode());
-    }
-
-    @Test
-    public void testNotEquals() {
-        CompilationUnit p1 = JavaParser.parse("class X { }");
-        CompilationUnit p2 = JavaParser.parse("class Y { }");
-        assertNotEquals(p1.hashCode(), p2.hashCode());
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/ModifierVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/ModifierVisitorTest.java
deleted file mode 100644
index ada0c6f..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/ModifierVisitorTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.visitor;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.BodyDeclaration;
-import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseExpression;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class ModifierVisitorTest {
-    @Test
-    public void makeSureParentListsCanBeModified() {
-        NodeList<StringLiteralExpr> list = new NodeList<>();
-        list.add(new StringLiteralExpr("t"));
-        list.add(new StringLiteralExpr("a"));
-        list.add(new StringLiteralExpr("b"));
-        list.add(new StringLiteralExpr("c"));
-
-        list.accept(new ModifierVisitor<Void>() {
-            @Override
-            public Visitable visit(final StringLiteralExpr n, final Void arg) {
-                String v = n.getValue();
-
-                list.addFirst(new StringLiteralExpr("extra " + v));
-                list.remove(new StringLiteralExpr("t"));
-
-                if (v.equals("a")) {
-                    return new StringLiteralExpr("x");
-                }
-                if (v.equals("b")) {
-                    return null;
-                }
-
-                return n;
-            }
-        }, null);
-
-        assertEquals("extra c", list.get(0).getValue());
-        assertEquals("extra b", list.get(1).getValue());
-        assertEquals("extra a", list.get(2).getValue());
-        assertEquals("extra t", list.get(3).getValue());
-        assertEquals("x", list.get(4).getValue());
-        assertEquals("c", list.get(5).getValue());
-        assertEquals(6, list.size());
-    }
-
-    @Test
-    public void binaryExprReturnsLeftExpressionWhenRightSideIsRemoved() {
-        Expression expression = parseExpression("1+2");
-        Visitable result = expression.accept(new ModifierVisitor<Void>() {
-            public Visitable visit(IntegerLiteralExpr integerLiteralExpr, Void arg) {
-                if (integerLiteralExpr.getValue().equals("1")) {
-                    return null;
-                }
-                return integerLiteralExpr;
-            }
-        }, null);
-        assertEquals("2", result.toString());
-    }
-
-    @Test
-    public void binaryExprReturnsRightExpressionWhenLeftSideIsRemoved() {
-        final Expression expression = parseExpression("1+2");
-        final Visitable result = expression.accept(new ModifierVisitor<Void>() {
-            public Visitable visit(IntegerLiteralExpr integerLiteralExpr, Void arg) {
-                if (integerLiteralExpr.getValue().equals("2")) {
-                    return null;
-                }
-                return integerLiteralExpr;
-            }
-        }, null);
-        assertEquals("1", result.toString());
-    }
-
-    @Test
-    public void fieldDeclarationCantSurviveWithoutVariables() {
-        final BodyDeclaration<?> bodyDeclaration = JavaParser.parseBodyDeclaration("int x=1;");
-
-        final Visitable result = bodyDeclaration.accept(new ModifierVisitor<Void>() {
-            public Visitable visit(VariableDeclarator x, Void arg) {
-                return null;
-            }
-        }, null);
-
-        assertEquals(null, result);
-    }
-
-    @Test
-    public void variableDeclarationCantSurviveWithoutVariables() {
-        final BodyDeclaration<?> bodyDeclaration = JavaParser.parseBodyDeclaration("void x() {int x=1;}");
-
-        final Visitable result = bodyDeclaration.accept(new ModifierVisitor<Void>() {
-            public Visitable visit(VariableDeclarator x, Void arg) {
-                return null;
-            }
-        }, null);
-
-        assertEquals("void x() {" + EOL + "}", result.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitorTest.java
deleted file mode 100644
index 1e2cdf8..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentEqualsVisitorTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*

- * 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.visitor;

-

-import static org.junit.Assert.assertFalse;

-import static org.junit.Assert.assertTrue;

-

-import org.junit.Test;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ast.CompilationUnit;

-

-public class NoCommentEqualsVisitorTest {

-

-    @Test

-    public void testEquals() {

-        CompilationUnit p1 = JavaParser.parse("class X { }");

-        CompilationUnit p2 = JavaParser.parse("class X { }");

-        assertTrue(NoCommentEqualsVisitor.equals(p1, p2));

-    }

-

-    @Test

-    public void testEqualsWithDifferentComments() {

-        CompilationUnit p1 = JavaParser.parse("/* a */ class X { /** b */} //c");

-        CompilationUnit p2 = JavaParser.parse("/* b */ class X { }  //c");

-        assertTrue(NoCommentEqualsVisitor.equals(p1, p2));

-    }

-

-    @Test

-    public void testNotEquals() {

-        CompilationUnit p1 = JavaParser.parse("class X { }");

-        CompilationUnit p2 = JavaParser.parse("class Y { }");

-        assertFalse(NoCommentEqualsVisitor.equals(p1, p2));

-    }

-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitorTest.java
deleted file mode 100644
index 5065669..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/NoCommentHashCodeVisitorTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.github.javaparser.ast.visitor;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ast.CompilationUnit;

-import org.junit.Test;

-

-import static org.junit.Assert.assertEquals;

-import static org.junit.Assert.assertNotEquals;

-

-public class NoCommentHashCodeVisitorTest {

-

-    @Test

-    public void testEquals() {

-        CompilationUnit p1 = JavaParser.parse("class X { }");

-        CompilationUnit p2 = JavaParser.parse("class X { }");

-        assertEquals(p1.hashCode(), p2.hashCode());

-    }

-

-    @Test

-    public void testEqualsWithDifferentComments() {

-        CompilationUnit p1 = JavaParser.parse("/* a */ class X { /** b */} //c");

-        CompilationUnit p2 = JavaParser.parse("/* b */ class X { }  //c");

-        assertEquals(p1.hashCode(), p2.hashCode());

-        assertEquals(p1.getComments().size(), 3);

-        assertEquals(p2.getComments().size(), 2);

-    }

-

-    @Test

-    public void testNotEquals() {

-        CompilationUnit p1 = JavaParser.parse("class X { }");

-        CompilationUnit p2 = JavaParser.parse("class Y { }");

-        assertNotEquals(p1.hashCode(), p2.hashCode());

-    }

-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/TreeVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/TreeVisitorTest.java
deleted file mode 100644
index 53d3753..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/ast/visitor/TreeVisitorTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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.visitor;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.expr.ArrayInitializerExpr;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.expr.SimpleName;
-import org.junit.Test;
-
-import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
-import static org.junit.Assert.assertEquals;
-
-public class TreeVisitorTest {
-    @Test
-    public void isValidBreadthFirstTraversal() {
-        Expression expression = JavaParser.parseExpression("(2+3)+(4+5)");
-
-        StringBuilder result = new StringBuilder();
-
-        TreeVisitor visitor = new TreeVisitor() {
-            @Override
-            public void process(Node node) {
-                result.append("<").append(node).append("> ");
-            }
-        };
-
-        visitor.visitBreadthFirst(expression);
-        assertEquals("<(2 + 3) + (4 + 5)> <(2 + 3)> <(4 + 5)> <2 + 3> <4 + 5> <2> <3> <4> <5> ", result.toString());
-    }
-
-    @Test
-    public void issue743ConcurrentModificationProblem() {
-        Expression expression = JavaParser.parseExpression("new int[]{1,2,3,4}");
-
-        StringBuilder result = new StringBuilder();
-        TreeVisitor visitor = new TreeVisitor() {
-            @Override
-            public void process(Node node) {
-                if (node instanceof IntegerLiteralExpr) {
-                    node.getParentNode().ifPresent(
-                            parent -> ((ArrayInitializerExpr) parent).getValues().add(new IntegerLiteralExpr("1")));
-                }
-                result.append("<").append(node).append("> ");
-            }
-        };
-        visitor.visitPreOrder(expression);
-        System.out.println(result);
-    }
-
-    @Test
-    public void isValidPreOrderTraversal() {
-        StringBuilder result = new StringBuilder();
-        new TreeVisitor() {
-            @Override
-            public void process(Node node) {
-                result.append("<").append(node).append("> ");
-            }
-        }.visitPreOrder(JavaParser.parseExpression("(2+3)+(4+5)"));
-        assertEquals("<(2 + 3) + (4 + 5)> <(2 + 3)> <2 + 3> <2> <3> <(4 + 5)> <4 + 5> <4> <5> ", result.toString());
-    }
-
-    @Test
-    public void isValidPostOrderTraversal() {
-        StringBuilder result = new StringBuilder();
-        new TreeVisitor() {
-            @Override
-            public void process(Node node) {
-                result.append("<").append(node).append("> ");
-            }
-        }.visitPostOrder(JavaParser.parseExpression("(2+3)+(4+5)"));
-        assertEquals("<2> <3> <2 + 3> <(2 + 3)> <4> <5> <4 + 5> <(4 + 5)> <(2 + 3) + (4 + 5)> ", result.toString());
-    }
-
-    @Test
-    public void preOrderConcurrentModificationIsOk() {
-        new TreeVisitor() {
-            @Override
-            public void process(Node node) {
-                if (node instanceof IntegerLiteralExpr) {
-                    node.getParentNode().ifPresent(
-                            parent -> ((ArrayInitializerExpr) parent).getValues().add(new IntegerLiteralExpr("1")));
-                }
-            }
-        }.visitPreOrder(JavaParser.parseExpression("new int[]{1,2,3,4}"));
-    }
-
-    @Test
-    public void postOrderConcurrentModificationIsOk() {
-        new TreeVisitor() {
-            @Override
-            public void process(Node node) {
-                if (node instanceof IntegerLiteralExpr) {
-                    node.getParentNode().ifPresent(
-                            parent -> ((ArrayInitializerExpr) parent).getValues().add(new IntegerLiteralExpr("1")));
-                }
-            }
-        }.visitPostOrder(JavaParser.parseExpression("new int[]{1,2,3,4}"));
-    }
-
-    @Test
-    public void parents() {
-        CompilationUnit cu = JavaParser.parse("class X{int x=1;}");
-        SimpleName x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariable(0).getName();
-
-        Node.ParentsVisitor visitor = new Node.ParentsVisitor(x);
-        assertEquals("x = 1", visitor.next().toString());
-        assertEquals("int x = 1;", visitor.next().toString());
-        assertEqualsNoEol("class X {\n" +
-                "\n" +
-                "    int x = 1;\n" +
-                "}", visitor.next().toString());
-        assertEqualsNoEol("class X {\n" +
-                "\n" +
-                "    int x = 1;\n" +
-                "}\n", visitor.next().toString());
-        assertEquals(false, visitor.hasNext());
-    }
-
-    @Test
-    public void isValidDirectChildrenTraversal() {
-        Expression expression = JavaParser.parseExpression("(2+3)+(4+5)");
-
-        StringBuilder result = new StringBuilder();
-
-        TreeVisitor visitor = new TreeVisitor() {
-            @Override
-            public void process(Node node) {
-                result.append("<").append(node).append("> ");
-            }
-        };
-
-        visitor.visitDirectChildren(expression);
-        assertEquals("<(2 + 3)> <(4 + 5)> ", result.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/BasicJBehaveTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/BasicJBehaveTest.java
deleted file mode 100644
index 4e0fe6a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/BasicJBehaveTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.bdd;
-
-
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.configuration.Configuration;
-import org.jbehave.core.configuration.MostUsefulConfiguration;
-import org.jbehave.core.failures.FailingUponPendingStep;
-import org.jbehave.core.io.LoadFromClasspath;
-import org.jbehave.core.io.StoryFinder;
-import org.jbehave.core.junit.JUnitStories;
-import org.jbehave.core.reporters.Format;
-import org.jbehave.core.reporters.StoryReporterBuilder;
-
-import java.util.List;
-
-import static org.jbehave.core.io.CodeLocations.codeLocationFromClass;
-
-abstract class BasicJBehaveTest extends JUnitStories {
-
-    private final String storiesPath;
-
-    public BasicJBehaveTest(String storiesPath) {
-        this.storiesPath = storiesPath;
-        JUnitReportingRunner.recommendedControls(configuredEmbedder());
-    }
-
-    @Override
-    public final Configuration configuration() {
-        return new MostUsefulConfiguration()
-                // where to find the stories
-                .useStoryLoader(new LoadFromClasspath(this.getClass()))
-                // Fails if Steps are not implemented
-                .usePendingStepStrategy(new FailingUponPendingStep())
-                // CONSOLE and HTML reporting
-                .useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats()
-                        .withFormats(Format.CONSOLE, Format.HTML));
-    }
-
-    @Override
-    public final List<String> storyPaths() {
-        return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), storiesPath, "");
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/CommentParsingTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/CommentParsingTest.java
deleted file mode 100644
index 1ff3619..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/CommentParsingTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.bdd;
-
-import com.github.javaparser.bdd.steps.CommentParsingSteps;
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.steps.InjectableStepsFactory;
-import org.jbehave.core.steps.InstanceStepsFactory;
-import org.junit.runner.RunWith;
-
-@RunWith(JUnitReportingRunner.class)
-public class CommentParsingTest extends BasicJBehaveTest {
-
-    @Override
-    public InjectableStepsFactory stepsFactory() {
-        return new InstanceStepsFactory(configuration(), new CommentParsingSteps());
-    }
-
-    public CommentParsingTest() {
-        super("**/bdd/comment*.story");
-    }
-}
-
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/ComparingTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/ComparingTest.java
deleted file mode 100644
index 4ecafd7..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/ComparingTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.bdd;
-
-import com.github.javaparser.bdd.steps.ComparingSteps;
-import com.github.javaparser.bdd.steps.SharedSteps;
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.steps.InjectableStepsFactory;
-import org.jbehave.core.steps.InstanceStepsFactory;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(JUnitReportingRunner.class)
-public class ComparingTest extends BasicJBehaveTest {
-
-    @Override
-    public InjectableStepsFactory stepsFactory() {
-        Map<String, Object> state = new HashMap<>();
-
-        return new InstanceStepsFactory(configuration(),
-                new SharedSteps(state),
-                new ComparingSteps());
-    }
-
-    public ComparingTest() {
-        super("**/bdd/comparing*.story");
-    }
-}
-
-
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/ManipulationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/ManipulationTest.java
deleted file mode 100644
index 0f24632..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/ManipulationTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.bdd;
-
-import com.github.javaparser.bdd.steps.ManipulationSteps;
-import com.github.javaparser.bdd.steps.SharedSteps;
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.steps.InjectableStepsFactory;
-import org.jbehave.core.steps.InstanceStepsFactory;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(JUnitReportingRunner.class)
-public class ManipulationTest extends BasicJBehaveTest {
-
-    @Override
-    public InjectableStepsFactory stepsFactory() {
-        Map<String, Object> state = new HashMap<>();
-
-        return new InstanceStepsFactory(configuration(),
-                new SharedSteps(state),
-                new ManipulationSteps(state));
-    }
-
-    public ManipulationTest() {
-        super("**/bdd/manipulation*.story");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/ParsingTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/ParsingTest.java
deleted file mode 100644
index d05d57a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/ParsingTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.bdd;
-
-import com.github.javaparser.bdd.steps.ParsingSteps;
-import com.github.javaparser.bdd.steps.SharedSteps;
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.steps.InjectableStepsFactory;
-import org.jbehave.core.steps.InstanceStepsFactory;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(JUnitReportingRunner.class)
-public class ParsingTest extends BasicJBehaveTest {
-
-    @Override
-    public InjectableStepsFactory stepsFactory() {
-        Map<String, Object> state = new HashMap<>();
-
-        return new InstanceStepsFactory(configuration(),
-                new SharedSteps(state),
-                new ParsingSteps(state));
-    }
-
-    public ParsingTest() {
-        super("**/bdd/parsing*.story");
-    }
-}
-
-
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/PositionRangeTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/PositionRangeTest.java
deleted file mode 100644
index e7f5b28..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/PositionRangeTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.bdd;
-
-import com.github.javaparser.bdd.steps.PositionRangeSteps;
-import com.github.javaparser.bdd.steps.SharedSteps;
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.steps.InjectableStepsFactory;
-import org.jbehave.core.steps.InstanceStepsFactory;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(JUnitReportingRunner.class)
-public class PositionRangeTest extends BasicJBehaveTest {
-
-    @Override
-    public InjectableStepsFactory stepsFactory() {
-        Map<String, Object> state = new HashMap<>();
-
-        return new InstanceStepsFactory(configuration(),
-                new SharedSteps(state),
-                new PositionRangeSteps());
-    }
-
-    public PositionRangeTest() {
-        super("**/bdd/position_range*.story");
-    }
-}
-
-
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/PrettyPrintingTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/PrettyPrintingTest.java
deleted file mode 100644
index 7540d3b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/PrettyPrintingTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.bdd;
-
-import com.github.javaparser.bdd.steps.PrettyPrintingSteps;
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.steps.InjectableStepsFactory;
-import org.jbehave.core.steps.InstanceStepsFactory;
-import org.junit.runner.RunWith;
-
-@RunWith(JUnitReportingRunner.class)
-public class PrettyPrintingTest extends BasicJBehaveTest {
-
-    @Override
-    public InjectableStepsFactory stepsFactory() {
-        return new InstanceStepsFactory(configuration(), new PrettyPrintingSteps());
-    }
-
-    public PrettyPrintingTest() {
-        super("**/bdd/pretty_printing*.story");
-    }
-}
-
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/TestUtils.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/TestUtils.java
deleted file mode 100644
index 784a113..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/TestUtils.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.bdd;
-
-import java.io.InputStream;
-
-public class TestUtils {
-
-    public static InputStream getSampleStream(String sampleName) {
-        InputStream is = TestUtils.class.getClassLoader().getResourceAsStream("com/github/javaparser/bdd/samples/"
-                + sampleName + ".java");
-        if (is == null) {
-            throw new RuntimeException("Example not found, check your test. Sample name: " + sampleName);
-        }
-        return is;
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/VisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/VisitorTest.java
deleted file mode 100644
index 442c2ed..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/VisitorTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.bdd;
-
-import com.github.javaparser.bdd.steps.SharedSteps;
-import com.github.javaparser.bdd.steps.VisitorSteps;
-import com.github.valfirst.jbehave.junit.monitoring.JUnitReportingRunner;
-import org.jbehave.core.steps.InjectableStepsFactory;
-import org.jbehave.core.steps.InstanceStepsFactory;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(JUnitReportingRunner.class)
-public class VisitorTest extends BasicJBehaveTest {
-
-    @Override
-    public InjectableStepsFactory stepsFactory() {
-        Map<String, Object> state = new HashMap<>();
-        return new InstanceStepsFactory(configuration(),
-                new SharedSteps(state),
-                new VisitorSteps(state));
-    }
-
-    public VisitorTest() {
-        super("**/bdd/visitor*.story");
-    }
-}
-
-
-
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/CommentParsingSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/CommentParsingSteps.java
deleted file mode 100644
index 3257c43..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/CommentParsingSteps.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.Range;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.comments.*;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.stmt.BlockStmt;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.ast.type.PrimitiveType;
-import com.github.javaparser.printer.PrettyPrinter;
-import com.github.javaparser.printer.PrettyPrinterConfiguration;
-import org.jbehave.core.annotations.Alias;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-import org.jbehave.core.annotations.When;
-import org.jbehave.core.model.ExamplesTable;
-import org.jbehave.core.steps.Parameters;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Iterator;
-import java.util.Set;
-
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.Range.range;
-import static com.github.javaparser.bdd.TestUtils.getSampleStream;
-import static com.github.javaparser.bdd.steps.SharedSteps.getMemberByTypeAndPosition;
-import static org.hamcrest.CoreMatchers.*;
-import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class CommentParsingSteps {
-
-    private CompilationUnit compilationUnit;
-    private CommentsCollection commentsCollection;
-    private String sourceUnderTest;
-    private ParserConfiguration configuration = new ParserConfiguration();
-    private PrettyPrinter prettyPrinter = new PrettyPrinter(new PrettyPrinterConfiguration());
-
-    @Given("the class:$classSrc")
-    public void givenTheClass(String classSrc) {
-        this.sourceUnderTest = classSrc.trim();
-    }
-
-    @When("read sample \"$sampleName\" using encoding \"$encoding\"")
-    public void givenTheClassWithEncoding(String sampleName, String encoding) throws IOException {
-        sourceUnderTest = null;
-        ParseResult<CompilationUnit> parseResult = new JavaParser(new ParserConfiguration()).parse(COMPILATION_UNIT, provider(getSampleStream(sampleName), Charset.forName(encoding)));
-        commentsCollection = parseResult.getCommentsCollection().orElse(new CommentsCollection());
-    }
-
-    @When("the class is parsed by the comment parser")
-    public void whenTheClassIsParsedByTheCommentParser() throws IOException {
-        ParseResult<CompilationUnit> parseResult = new JavaParser(new ParserConfiguration()).parse(COMPILATION_UNIT, provider(sourceUnderTest));
-        commentsCollection = parseResult.getCommentsCollection().orElse(new CommentsCollection());
-    }
-
-    @When("the do not consider annotations as node start for code attribution is $value on the Java parser")
-    public void whenTheDoNotConsiderAnnotationsAsNodeStartForCodeAttributionIsTrueOnTheJavaParser(boolean value) {
-        configuration.setDoNotConsiderAnnotationsAsNodeStartForCodeAttribution(value);
-    }
-
-    @When("the do not assign comments preceding empty lines is $value on the Java parser")
-    public void whenTheDoNotAssignCommentsPrecedingEmptyLinesIsTrueOnTheJavaParser(boolean value) {
-        configuration.setDoNotAssignCommentsPrecedingEmptyLines(value);
-    }
-
-    @When("the class is parsed by the Java parser")
-    public void whenTheClassIsParsedByTheJavaParser() {
-        ParseResult<CompilationUnit> result = new JavaParser(configuration).parse(COMPILATION_UNIT, provider(sourceUnderTest));
-        compilationUnit = result.getResult().get();
-    }
-
-    @Then("the Java parser cannot parse it because of an error")
-    public void javaParserCannotParseBecauseOfLexicalErrors() {
-        ParseResult<CompilationUnit> result = new JavaParser(configuration).parse(COMPILATION_UNIT, provider(sourceUnderTest));
-        if (result.isSuccessful()) {
-            fail("Lexical error expected");
-        }
-    }
-
-    @Then("the total number of comments is $expectedCount")
-    public void thenTheTotalNumberOfCommentsIs(int expectedCount) {
-        assertThat(commentsCollection.size(), is(expectedCount));
-    }
-
-    private <T extends Comment> T getCommentAt(Set<T> set, int index) {
-        Iterator<T> iterator = set.iterator();
-        T comment = null;
-        while (index >= 0) {
-            comment = iterator.next();
-            index--;
-        }
-        return comment;
-    }
-
-    @Then("line comment $position is \"$expectedContent\"")
-    public void thenLineCommentIs(int position, String expectedContent) {
-        LineComment lineCommentUnderTest = getCommentAt(commentsCollection.getLineComments(), position - 1);
-
-        assertThat(lineCommentUnderTest.getContent(), is(expectedContent));
-    }
-
-    @Then("block comment $position is \"$expectedContent\"")
-    public void thenBlockCommentIs(int position, String expectedContent) {
-        BlockComment lineCommentUnderTest = getCommentAt(commentsCollection.getBlockComments(), position - 1);
-
-        assertThat(lineCommentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("Javadoc comment $position is \"$expectedContent\"")
-    public void thenJavadocCommentIs(int position, String expectedContent) {
-        JavadocComment commentUnderTest = getCommentAt(commentsCollection.getJavadocComments(), position - 1);
-
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("the line comments have the following positions: $table")
-    public void thenTheLineCommentsHaveTheFollowingPositions(ExamplesTable examplesTable) {
-        int index = 0;
-        for (Parameters exampleRow : examplesTable.getRowsAsParameters()) {
-            Comment expectedLineComment = toComment(exampleRow, new LineComment());
-            Comment lineCommentUnderTest = getCommentAt(commentsCollection.getLineComments(), index);
-
-            Range underTestRange = lineCommentUnderTest.getRange().get();
-            Range expectedRange = expectedLineComment.getRange().get();
-
-            assertThat(underTestRange.begin.line, is(expectedRange.begin.line));
-            assertThat(underTestRange.begin.column, is(expectedRange.begin.column));
-            assertThat(underTestRange.end.line, is(expectedRange.end.line));
-            assertThat(underTestRange.end.column, is(expectedRange.end.column));
-            index++;
-        }
-    }
-
-    @Then("the block comments have the following positions: $table")
-    public void thenTheBlockCommentsHaveTheFollowingPositions(ExamplesTable examplesTable) {
-        int index = 0;
-        for (Parameters exampleRow : examplesTable.getRowsAsParameters()) {
-            Comment expectedLineComment = toComment(exampleRow, new BlockComment());
-            Comment lineCommentUnderTest = getCommentAt(commentsCollection.getBlockComments(), index);
-
-            Range underTestRange = lineCommentUnderTest.getRange().get();
-            Range expectedRange = expectedLineComment.getRange().get();
-
-            assertThat(underTestRange.begin.line, is(expectedRange.begin.line));
-            assertThat(underTestRange.begin.column, is(expectedRange.begin.column));
-            assertThat(underTestRange.end.line, is(expectedRange.end.line));
-            assertThat(underTestRange.end.column, is(expectedRange.end.column));
-            index++;
-        }
-    }
-
-    @Then("the Javadoc comments have the following positions: $table")
-    public void thenTheJavadocCommentsHaveTheFollowingPositions(ExamplesTable examplesTable) {
-        int index = 0;
-        for (Parameters exampleRow : examplesTable.getRowsAsParameters()) {
-            Comment expectedLineComment = toComment(exampleRow, new BlockComment());
-            Comment lineCommentUnderTest = getCommentAt(commentsCollection.getJavadocComments(), index);
-
-            Range underTestRange = lineCommentUnderTest.getRange().get();
-            Range expectedRange = expectedLineComment.getRange().get();
-
-            assertThat(underTestRange.begin.line, is(expectedRange.begin.line));
-            assertThat(underTestRange.begin.column, is(expectedRange.begin.column));
-            assertThat(underTestRange.end.line, is(expectedRange.end.line));
-            assertThat(underTestRange.end.column, is(expectedRange.end.column));
-            index++;
-        }
-    }
-
-    @Then("it is printed as:$src")
-    public void isPrintedAs(String src) {
-        assertThat(prettyPrinter.print(compilationUnit).trim(), is(src.trim()));
-    }
-
-    @Then("the compilation unit is not commented")
-    public void thenTheCompilationUnitIsNotCommented() {
-        assertEquals(false, compilationUnit.getComment().isPresent());
-    }
-
-    @Then("the compilation is commented \"$expectedContent\"")
-    public void thenTheCompilationIsCommentedCompilationUnitComment(String expectedContent) {
-        assertThat(compilationUnit.getComment().get().getContent(), is(expectedContent));
-    }
-
-    @Then("the compilation unit has $expectedCount contained comments")
-    public void thenTheCompilationUnitHasContainedComments(int expectedCount) {
-        assertThat(compilationUnit.getComments().size(), is(expectedCount));
-    }
-
-    @Then("the compilation unit has $expectedCount orphan comments")
-    public void thenTheCompilationUnitHasExpectedCountOrphanComments(int expectedCount) {
-        assertThat(compilationUnit.getOrphanComments().size(), is(expectedCount));
-    }
-
-    @Then("the compilation unit orphan comment $position is \"$expectedContent\"")
-    public void thenTheCompilationUnitOrphanCommentIs(int position, String expectedContent) {
-        Comment commentUnderTest = compilationUnit.getOrphanComments().get(position - 1);
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("comment $commentPosition in compilation unit is not an orphan")
-    public void thenCommentInCompilationUnitIsNotAnOrphan(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.isOrphan(), is(false));
-    }
-
-    @Then("comment $commentPosition in compilation unit is an orphan")
-    public void thenCommentInCompilationUnitIsAnOrphan(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.isOrphan(), is(true));
-    }
-
-    @Then("comment $commentPosition in compilation unit is \"$expectedContent\"")
-    public void thenCommentInCompilationUnitIs(int position, String expectedContent) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(position - 1);
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("class $position is not commented")
-    public void thenClassIsNotCommented(int position) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
-        assertEquals(false, classUnderTest.getComment().isPresent());
-    }
-
-    @Then("class $position is commented \"$expectedContent\"")
-    public void thenClassIsCommented(int position, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
-        assertThat(classUnderTest.getComment().get().getContent(), is(expectedContent));
-    }
-
-    @Then("class $position has $expectedCount total contained comments")
-    public void thenClassHasTotalContainedComments(int position, int expectedCount) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
-        assertThat(classUnderTest.getAllContainedComments().size(), is(expectedCount));
-    }
-
-    @Then("class $position has $expectedCount orphan comment")
-    @Alias("class $position has $expectedCount orphan comments")
-    public void thenClassHasOrphanComments(int position, int expectedCount) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(position - 1);
-        assertThat(classUnderTest.getOrphanComments().size(), is(expectedCount));
-    }
-
-    @Then("class $classPosition orphan comment $commentPosition is \"$expectedContent\"")
-    public void thenClassOrphanCommentIs(int classPosition, int commentPosition, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        Comment commentUnderTest = classUnderTest.getOrphanComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("method $methodPosition in class $classPosition is commented \"$expectedContent\"")
-    public void thenMethodInClassIsCommented(int methodPosition, int classPosition, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        assertThat(methodUnderTest.getComment().get().getContent(), equalToIgnoringWhiteSpace(expectedContent));
-    }
-
-    @Then("method $methodPosition in class $classPosition has $expectedCount total contained comments")
-    public void thenMethodInClassHasTotalContainedComments(int methodPosition, int classPosition, int expectedCount) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        assertThat(methodUnderTest.getAllContainedComments().size(), is(expectedCount));
-    }
-
-    @Then("comment $commentPosition in method $methodPosition in class $classPosition is \"$expectedContent\"")
-    public void thenCommentInMethodInClassIs(int commentPosition, int methodPosition, int classPosition, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        Comment commentUnderTest = methodUnderTest.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("method $methodPosition in class $classPosition has $expectedCount orphan comments")
-    public void thenMethodInClassHasOrphanComments(int methodPosition, int classPosition, int expectedCount) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        assertThat(methodUnderTest.getOrphanComments().size(), is(expectedCount));
-    }
-
-    @Then("block statement in method $methodPosition in class $classPosition has $expectedCount total contained comments")
-    public void thenBlockStatementInMethodInClassHasTotalContainedComments(int methodPosition, int classPosition, int expectedCount) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        BlockStmt blockStmtUnderTest = methodUnderTest.getBody().orElse(null);
-        assertThat(blockStmtUnderTest.getAllContainedComments().size(), is(expectedCount));
-    }
-
-    @Then("block statement in method $methodPosition in class $classPosition has $expectedCount orphan comments")
-    public void thenBlockStatementInMethodInClassHasOrphanComments(int methodPosition, int classPosition, int expectedCount) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        BlockStmt blockStmtUnderTest = methodUnderTest.getBody().orElse(null);
-        assertThat(blockStmtUnderTest.getOrphanComments().size(), is(expectedCount));
-    }
-
-    @Then("block statement in method $methodPosition in class $classPosition orphan comment $commentPosition is \"$expectedContent\"")
-    public void thenBlockStatementInMethodInClassIs(int methodPosition, int classPosition, int commentPosition, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        BlockStmt blockStmtUnderTest = methodUnderTest.getBody().orElse(null);
-        Comment commentUnderTest = blockStmtUnderTest.getOrphanComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("type of method $methodPosition in class $classPosition is commented \"$expectedContent\"")
-    public void thenTypeOfMethodInClassIsCommented(int methodPosition, int classPosition, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        MethodDeclaration methodUnderTest = getMemberByTypeAndPosition(classUnderTest, methodPosition - 1,
-                MethodDeclaration.class);
-        Comment commentUnderTest = methodUnderTest.getType().getComment().get();
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("field $fieldPosition in class $classPosition contains $expectedCount comments")
-    public void thenFieldInClassContainsComments(int fieldPosition, int classPosition, int expectedCount) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
-                FieldDeclaration.class);
-        assertThat(fieldUnderTest.getAllContainedComments().size(), is(expectedCount));
-    }
-
-    @Then("field $fieldPosition in class $classPosition is not commented")
-    public void thenFieldInClassIsNotCommented(int fieldPosition, int classPosition) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
-                FieldDeclaration.class);
-        assertEquals(false, fieldUnderTest.getComment().isPresent());
-    }
-
-    @Then("field $fieldPosition in class $classPosition is commented \"$expectedContent\"")
-    public void thenFieldInClassIsCommented(int fieldPosition, int classPosition, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
-                FieldDeclaration.class);
-        Comment commentUnderTest = fieldUnderTest.getComment().get();
-        assertThat(commentUnderTest.getContent(), is(equalToIgnoringWhiteSpace(expectedContent)));
-    }
-
-    @Then("variable $variablePosition value of field $fieldPosition in class $classPosition is commented \"$expectedContent\"")
-    public void thenVariableValueOfFieldInClassIsCommented(int variablePosition, int fieldPosition, int classPosition, String expectedContent) {
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
-                FieldDeclaration.class);
-        VariableDeclarator variableUnderTest = fieldUnderTest.getVariable(variablePosition - 1);
-        Expression valueUnderTest = variableUnderTest.getInitializer().orElse(null);
-        Comment commentUnderTest = valueUnderTest.getComment().get();
-        assertThat(commentUnderTest.getContent(), is(expectedContent));
-    }
-
-    @Then("comment $commentPosition in compilation unit parent is ClassOrInterfaceDeclaration")
-    public void thenCommentInCompilationUnitParentIsClassOrInterfaceDeclaration(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getParentNode().get(), instanceOf(ClassOrInterfaceDeclaration.class));
-    }
-
-    @Then("comment $commentPosition in compilation unit commented node is ClassOrInterfaceDeclaration")
-    public void thenCommentInCompilationUnitCommentedNodeIsClassOrInterfaceDeclaration(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(ClassOrInterfaceDeclaration.class));
-    }
-
-    @Then("comment $commentPosition in compilation unit commented node is FieldDeclaration")
-    public void thenCommentInCompilationUnitCommentedNodeIsFieldDeclaration(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(FieldDeclaration.class));
-    }
-
-    @Then("comment $commentPosition in compilation unit commented node is IntegerLiteralExpr")
-    public void thenCommentInCompilationUnitCommentedNodeIsIntegerLiteralExpr(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(IntegerLiteralExpr.class));
-    }
-
-    @Then("comment $commentPosition in compilation unit commented node is ExpressionStmt")
-    public void thenCommentInCompilationUnitCommentedNodeIsIntegerExpressionStmt(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(ExpressionStmt.class));
-    }
-
-    @Then("comment $commentPosition in compilation unit commented node is PrimitiveType")
-    public void thenCommentInCompilationUnitCommentedNodeIsIntegerPrimitiveType(int commentPosition) {
-        Comment commentUnderTest = compilationUnit.getAllContainedComments().get(commentPosition - 1);
-        assertThat(commentUnderTest.getCommentedNode().get(), instanceOf(PrimitiveType.class));
-    }
-
-    private Comment toComment(Parameters row, Comment comment) {
-        comment.setRange(range(Integer.parseInt(row.values().get("beginLine")),
-                Integer.parseInt(row.values().get("beginColumn")),
-                Integer.parseInt(row.values().get("endLine")),
-                Integer.parseInt(row.values().get("endColumn"))));
-        return comment;
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ComparingSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ComparingSteps.java
deleted file mode 100644
index 4b789a7..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ComparingSteps.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-public class ComparingSteps {
-
-    private CompilationUnit first;
-    private CompilationUnit second;
-
-    /*
-     * Given steps
-     */
-
-    @Given("the first class:$classSrc")
-    public void givenTheFirstClass(String classSrc) {
-        this.first = JavaParser.parse(classSrc.trim());
-    }
-
-    @Given("the second class:$classSrc")
-    public void givenTheSecondClass(String classSrc) {
-        this.second = JavaParser.parse(classSrc.trim());
-    }
-
-    /*
-     * Then steps
-     */
-
-    @Then("they are equals")
-    public void thenTheyAreEquals() {
-        assertThat(first, is(equalTo(second)));
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ExistenceOfParentNodeVerifier.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ExistenceOfParentNodeVerifier.java
deleted file mode 100644
index 27d81b5..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ExistenceOfParentNodeVerifier.java
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.HasParentNode;
-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.expr.*;
-import com.github.javaparser.ast.stmt.*;
-import com.github.javaparser.ast.type.*;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
-
-import static org.hamcrest.Matchers.notNullValue;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * The <code>ExistenceOfParentNodeVerifier</code> verifies that each node of the compilation unit has a parent set.
- */
-class ExistenceOfParentNodeVerifier {
-
-    public void verify(CompilationUnit compilationUnit) throws AssertionError {
-        new Verifier().visit(compilationUnit, null);
-    }
-
-    private static class Verifier extends VoidVisitorAdapter<Void> {
-        private static void assertParentIsSet(HasParentNode<?> n) {
-            assertThat(n + " has no parent set!", n.getParentNode().orElse(null), is(notNullValue()));
-        }
-
-        @Override
-        public void visit(AnnotationDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(AnnotationMemberDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ArrayAccessExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ArrayCreationExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ArrayInitializerExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(AssertStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(AssignExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(BinaryExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(BlockComment n, Void arg) {
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(BlockStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(BooleanLiteralExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(BreakStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(CastExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(CatchClause n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(CharLiteralExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ClassExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ClassOrInterfaceDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ClassOrInterfaceType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(CompilationUnit n, Void arg) {
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ConditionalExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ConstructorDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ContinueStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(DoStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(DoubleLiteralExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(EmptyStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(EnclosedExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(EnumConstantDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(EnumDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ExplicitConstructorInvocationStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ExpressionStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(FieldAccessExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(FieldDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ForeachStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ForStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(IfStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(InitializerDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(InstanceOfExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(IntegerLiteralExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(JavadocComment n, Void arg) {
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(LabeledStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(LineComment n, Void arg) {
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(LambdaExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(LongLiteralExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(MarkerAnnotationExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(MemberValuePair n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(MethodCallExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(MethodDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(MethodReferenceExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(NameExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(NormalAnnotationExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(NullLiteralExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ObjectCreationExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(PackageDeclaration n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(Parameter n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(PrimitiveType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(Name n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(SimpleName n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ArrayType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ArrayCreationLevel n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(IntersectionType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(UnionType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ReturnStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(SingleMemberAnnotationExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(StringLiteralExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(SuperExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(SwitchEntryStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(SwitchStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(SynchronizedStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ThisExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(ThrowStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(TryStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(LocalClassDeclarationStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(TypeExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(NodeList n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(TypeParameter n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(UnaryExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(UnknownType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(VariableDeclarationExpr n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(VariableDeclarator n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(VoidType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(WhileStmt n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-
-        @Override
-        public void visit(WildcardType n, Void arg) {
-            assertParentIsSet(n);
-            super.visit(n, arg);
-        }
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ManipulationSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ManipulationSteps.java
deleted file mode 100644
index 557bf0d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ManipulationSteps.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.PackageDeclaration;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.body.TypeDeclaration;
-import com.github.javaparser.ast.expr.*;
-import com.github.javaparser.ast.stmt.BlockStmt;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.ast.stmt.TryStmt;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import com.github.javaparser.ast.type.VoidType;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
-import org.jbehave.core.annotations.Alias;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-import org.jbehave.core.annotations.When;
-
-import java.util.EnumSet;
-import java.util.Map;
-
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
-import static com.github.javaparser.JavaParser.parseName;
-import static com.github.javaparser.ast.NodeList.nodeList;
-import static com.github.javaparser.ast.type.PrimitiveType.*;
-import static com.github.javaparser.bdd.steps.SharedSteps.getMethodByPositionAndClassPosition;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertThat;
-
-public class ManipulationSteps {
-
-    /* Fields used to maintain step state within this step class */
-    private BlockStmt blockStmt;
-    private Statement statement;
-    private TryStmt tryStmt;
-    private NodeList<Expression> variableDeclarationExprList;
-    private ChangeMethodNameToUpperCaseVisitor changeMethodNameToUpperCaseVisitor;
-    private AddNewIntParameterCalledValueVisitor addNewIntParameterCalledValueVisitor;
-
-    /* Map that maintains shares state across step classes.  If manipulating the objects in the map you must update the state */
-    private Map<String, Object> state;
-
-    public ManipulationSteps(Map<String, Object> state) {
-        this.state = state;
-    }
-
-    @Given("a BlockStmt")
-    public void givenABlockStatement() {
-        blockStmt = new BlockStmt();
-    }
-
-    @Given("a Statement")
-    public void givenAStatement() {
-        statement = null;
-    }
-
-    @Given("a TryStmt")
-    public void givenATryStmt() {
-        tryStmt = new TryStmt();
-    }
-
-    @Given("a List of VariableDeclarations")
-    public void givenAListOfVariableDeclarations() {
-        variableDeclarationExprList = new NodeList<>();
-        variableDeclarationExprList.add(new VariableDeclarationExpr());
-        variableDeclarationExprList.add(new VariableDeclarationExpr());
-    }
-
-    @Given("a ChangeNameToUpperCaseVisitor")
-    public void givenAChangeNameToUpperCaseVisitor() {
-        changeMethodNameToUpperCaseVisitor = new ChangeMethodNameToUpperCaseVisitor();
-    }
-
-    @Given("a AddNewIntParameterCalledValueVisitor")
-    public void givenAAddNewParameterCalledValueVisitor() {
-        addNewIntParameterCalledValueVisitor = new AddNewIntParameterCalledValueVisitor();
-    }
-
-    @When("is the String \"$value\" is parsed by the JavaParser using parseBlock")
-    public void whenIsTheStringIsParsedByTheJavaParser(String value) {
-        blockStmt = JavaParser.parseBlock(value);
-    }
-
-    @When("is the String \"$value\" is parsed by the JavaParser using parseStatement")
-    public void whenIsTheStringIsParsedByTheJavaParserUsingParseStatement(String value) {
-        statement = JavaParser.parseStatement(value);
-    }
-
-    @When("the List of VariableDeclarations are set as the resources on TryStmt")
-    public void whenTheListOfVariableDeclarationsAreSetAsTheResourcesOnTryStmt() {
-        tryStmt.setResources(variableDeclarationExprList);
-    }
-
-    @When("empty list is set as the resources on TryStmt")
-    public void whenNullIsSetAsTheResourcesOnTryStmt() {
-        tryStmt.setResources(new NodeList<>());
-    }
-
-    @When("the package declaration is set to \"$packageName\"")
-    public void whenThePackageDeclarationIsSetTo(String packageName) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        compilationUnit.setPackageDeclaration(new PackageDeclaration(parseName(packageName)));
-        state.put("cu1", compilationUnit);
-    }
-
-    @When("a public class called \"$className\" is added to the CompilationUnit")
-    public void whenAClassCalledIsAddedToTheCompilationUnit(String className) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        TypeDeclaration<?> type = new ClassOrInterfaceDeclaration(EnumSet.of(Modifier.PUBLIC), false, "CreateClass");
-        compilationUnit.setTypes(nodeList(type));
-        state.put("cu1", compilationUnit);
-    }
-
-    @When("a public static method called \"$methodName\" returning void is added to class $position in the compilation unit")
-    public void whenAStaticMethodCalledReturningIsAddedToClassInTheCompilationUnit(String methodName, int position) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        TypeDeclaration<?> type = compilationUnit.getType(position - 1);
-        EnumSet<Modifier> modifiers = EnumSet.of(Modifier.PUBLIC);
-        MethodDeclaration method = new MethodDeclaration(modifiers, new VoidType(), methodName);
-        modifiers.add(Modifier.STATIC);
-        method.setModifiers(modifiers);
-        type.addMember(method);
-        state.put("cu1", compilationUnit);
-    }
-
-    @When("$typeName varargs called \"$parameterName\" are added to method $methodPosition in class $classPosition")
-    public void whenVarargsCalledAreAddedToMethodInClass(String typeName, String parameterName, int methodPosition, int classPosition) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition)
-                .addAndGetParameter(typeName, parameterName)
-                .setVarArgs(true);
-    }
-
-    @When("a BlockStmt is added to method $methodPosition in class $classPosition")
-    public void whenABlockStmtIsAddedToMethodInClass(int methodPosition, int classPosition) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-        method.setBody(new BlockStmt());
-    }
-
-    @When("$className.$fieldName.$methodName(\"$stringValue\"); is added to the body of method $methodPosition in class $classPosition")
-    public void whenHelloWorldIsAddedToTheBodyOfMethodInClass(String className, String fieldName, String methodName, String stringValue,
-                                                              int methodPosition, int classPosition) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-        NameExpr clazz = new NameExpr(className);
-        FieldAccessExpr field = new FieldAccessExpr(clazz, fieldName);
-        MethodCallExpr call = new MethodCallExpr(field, methodName);
-        call.addArgument(new StringLiteralExpr(stringValue));
-        method.getBody().get().addStatement(call);
-    }
-
-    @When("method $methodPosition in class $classPosition has it's name converted to uppercase")
-    public void whenMethodInClassHasItsNameConvertedToUppercase(int methodPosition, int classPosition) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-        method.setName(method.getNameAsString().toUpperCase());
-    }
-
-    @When("method $methodPosition in class $classPosition has an int parameter called \"$paramName\" added")
-    public void whenMethodInClassHasAnIntArgumentCalledAdded(int methodPosition, int classPosition, String paramName) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-        method.addParameter(intType(), paramName);
-    }
-
-    @When("the compilation unit is cloned")
-    public void whenTheCompilationUnitIsCloned() throws CloneNotSupportedException {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        state.put("cu1", compilationUnit.clone());
-    }
-
-    @When("the ChangeNameToUpperCaseVisitor visits to compilation unit")
-    public void whenTheVisitorVisitsToCompilationUnit() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        changeMethodNameToUpperCaseVisitor.visit(compilationUnit, null);
-        state.put("cu1", compilationUnit);
-    }
-
-    @When("the AddNewIntParameterCalledValueVisitor visits to compilation unit")
-    public void whenTheAddNewParameterCalledValueVisitorVisitsToCompilationUnit() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        addNewIntParameterCalledValueVisitor.visit(compilationUnit, null);
-        state.put("cu1", compilationUnit);
-    }
-
-    @Then("is not equal to null")
-    public void thenIsNotEqualToNull() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        assertNotEquals(compilationUnit, null);
-    }
-
-    @Then("is not equal to $value")
-    public void thenIsNotEqualTo(String value) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        assertNotEquals(compilationUnit, value);
-    }
-
-    @Then("Statement $position in BlockStmt toString is \"$expectedContent\"")
-    public void thenTheBlockStmtContentIs(int position, String expectedContent) {
-        Statement statementUnderTest = blockStmt.getStatement(position - 1);
-        assertThat(statementUnderTest.toString(), is(expectedContent));
-    }
-
-    @Then("Statement toString is \"$expectedContent\"")
-    public void thenStatementToStringIsxXy(String expectedContent) {
-        assertThat(statement.toString(), is(expectedContent));
-    }
-
-    @Then("all the VariableDeclarations parent is the TryStmt")
-    public void thenAllTheVariableDeclarationsParentIsTheTryStmt() {
-        variableDeclarationExprList.forEach(expr -> assertThat(expr.getParentNode().get(), is(tryStmt)));
-    }
-
-    @Then("the TryStmt has no child nodes")
-    public void thenTheTryStmtHasNotChildNodes() {
-        assertThat(tryStmt.getChildNodes().size(), is(0));
-    }
-
-    @Then("method $methodPosition in class $classPosition has the name \"$expectedName\"")
-    public void thenMethodInClassHasTheName(int methodPosition, int classPosition, String expectedName) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-        assertThat(method.getNameAsString(), is(expectedName));
-    }
-
-    @Then("method $methodPosition in class $classPosition has $expectedCount parameters")
-    @Alias("method $methodPosition in class $classPosition has $expectedCount parameter")
-    public void thenMethodInClassHasArguments(int methodPosition, int classPosition, int expectedCount) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-
-        assertThat(method.getParameters().size(), is(expectedCount));
-    }
-
-    @Then("method $methodPosition in class $classPosition parameter $parameterPosition is type int called \"$expectedName\"")
-    public void thenMethodInClassParameterIsTypeIntCalled(int methodPosition, int classPosition, int parameterPosition, String expectedName) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-        Parameter parameter = method.getParameter(parameterPosition - 1);
-        assertThat(parameter.getType(), is(intType()));
-        assertThat(parameter.getNameAsString(), is(expectedName));
-    }
-
-    private static class ChangeMethodNameToUpperCaseVisitor extends VoidVisitorAdapter<Void> {
-        @Override
-        public void visit(MethodDeclaration n, Void arg) {
-            n.setName(n.getNameAsString().toUpperCase());
-        }
-    }
-
-    private static class AddNewIntParameterCalledValueVisitor extends VoidVisitorAdapter<Void> {
-        @Override
-        public void visit(MethodDeclaration n, Void arg) {
-            n.addParameter(intType(), "value");
-        }
-    }
-}
-
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ParsingSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ParsingSteps.java
deleted file mode 100644
index 01631c6..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/ParsingSteps.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseResult;
-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.expr.*;
-import com.github.javaparser.ast.stmt.BlockStmt;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.ast.stmt.ReturnStmt;
-import com.github.javaparser.ast.stmt.Statement;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-import org.jbehave.core.annotations.When;
-
-import java.util.List;
-import java.util.Map;
-
-import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.bdd.steps.SharedSteps.getMemberByTypeAndPosition;
-import static com.github.javaparser.bdd.steps.SharedSteps.getMethodByPositionAndClassPosition;
-import static java.lang.String.format;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.*;
-
-public class ParsingSteps {
-
-    private Map<String, Object> state;
-
-    public ParsingSteps(Map<String, Object> state) {
-        this.state = state;
-    }
-
-    private String sourceUnderTest;
-
-    /*
-     * Given steps
-     */
-
-    @Given("the class:$classSrc")
-    public void givenTheClass(String classSrc) {
-        this.sourceUnderTest = classSrc.trim();
-    }
-
-
-    /*
-     * When steps
-     */
-
-    @When("I take the ArrayCreationExpr")
-    public void iTakeTheArrayCreationExpr() {
-        setSelectedNodeFromCompilationUnit(ArrayCreationExpr.class);
-    }
-
-    @When("I take the PackageDeclaration")
-    public void iTakeThePackageDeclaration() {
-        setSelectedNodeFromCompilationUnit(PackageDeclaration.class);
-    }
-
-    @When("I take the ObjectCreationExpr")
-    public void iTakeTheObjectCreationExpr() throws ClassNotFoundException {
-        setSelectedNodeFromCompilationUnit(ObjectCreationExpr.class);
-    }
-
-    /*
-     * Then steps
-     */
-
-    @Then("constructor $constructorPosition in class $classPosition declaration as a String is \"$expectedString\"")
-    public void thenTheConstructorDeclarationAsAStringIs(int constructorPosition, int classPosition, String expectedString) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
-        ConstructorDeclaration constructor = (ConstructorDeclaration) clazz.getMember(constructorPosition - 1);
-        assertThat(constructor.getDeclarationAsString(), is(expectedString));
-    }
-
-    @Then("constructor $constructorPosition in class $classPosition declaration short form as a String is \"$expectedString\"")
-    public void thenConstructorInClassDeclarationShortFormAsAStringIs(int constructorPosition, int classPosition, String expectedString) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
-        ConstructorDeclaration constructor = (ConstructorDeclaration) clazz.getMember(constructorPosition - 1);
-        assertThat(constructor.getDeclarationAsString(false, false), is(expectedString));
-    }
-
-    @Then("method $methodPosition in class $classPosition declaration as a String is \"$expectedString\"")
-    public void thenMethod1InClass1DeclarationAsAStringIs(int methodPosition, int classPosition, String expectedString) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
-        MethodDeclaration method = (MethodDeclaration) clazz.getMember(methodPosition - 1);
-        assertThat(method.getDeclarationAsString(), is(expectedString));
-    }
-
-    @Then("method $methodPosition in class $classPosition declaration as a String short form is \"$expectedString\"")
-    public void thenMethodInClassDeclarationAsAStringShortFormIs(int methodPosition, int classPosition, String expectedString) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        ClassOrInterfaceDeclaration clazz = (ClassOrInterfaceDeclaration) compilationUnit.getType(classPosition - 1);
-        MethodDeclaration method = (MethodDeclaration) clazz.getMember(methodPosition - 1);
-        assertThat(method.getDeclarationAsString(false, false), is(expectedString));
-    }
-
-    @Then("field $fieldPosition in class $classPosition contains annotation $annotationPosition value is \"$expectedValue\"")
-    public void thenFieldInClassContainsAnnotationValueIs(int fieldPosition, int classPosition, int annotationPosition, String expectedValue) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-
-        TypeDeclaration<?> classUnderTest = compilationUnit.getType(classPosition - 1);
-        FieldDeclaration fieldUnderTest = getMemberByTypeAndPosition(classUnderTest, fieldPosition - 1,
-                FieldDeclaration.class);
-        AnnotationExpr annotationUnderTest = fieldUnderTest.getAnnotation(annotationPosition - 1);
-        assertThat(annotationUnderTest.getChildNodes().get(1).toString(), is(expectedValue));
-    }
-
-    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition is called $expectedName")
-    public void thenLambdaInClassIsCalled(int statementPosition, int methodPosition, int classPosition, String expectedName) {
-        Statement statement = getStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        VariableDeclarationExpr expression = (VariableDeclarationExpr) ((ExpressionStmt) statement).getExpression();
-        VariableDeclarator variableDeclarator = expression.getVariable(0);
-        assertThat(variableDeclarator.getNameAsString(), is(expectedName));
-    }
-
-    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition body is \"$expectedBody\"")
-    public void thenLambdaInStatementInMethodInClassBody(int statementPosition, int methodPosition, int classPosition,
-                                                         String expectedBody) {
-        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        assertThat(lambdaExpr.getBody().toString(), is(expectedBody));
-    }
-
-    @Then("lambda in method call in statement $statementPosition in method $methodPosition in class $classPosition body is \"$expectedBody\"")
-    public void thenLambdaInMethodCallInStatementInMethodInClassBody(int statementPosition, int methodPosition, int classPosition,
-                                                                     String expectedBody) {
-        ExpressionStmt statement = getStatementInMethodInClass(statementPosition, methodPosition, classPosition).asExpressionStmt();
-        VariableDeclarationExpr variableDeclarationExpr = statement.getExpression().asVariableDeclarationExpr();
-        VariableDeclarator variableDeclarator = variableDeclarationExpr.getVariable(0);
-        MethodCallExpr methodCallExpr = (MethodCallExpr) variableDeclarator.getInitializer().orElse(null);
-        CastExpr castExpr = methodCallExpr.getArgument(0).asCastExpr();
-        LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
-        assertThat(lambdaExpr.getBody().toString(), is(expectedBody));
-    }
-
-    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition block statement is null")
-    public void thenLambdaInStatementInMethodInClassBlockStatementIsNull(int statementPosition, int methodPosition, int classPosition) {
-        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        BlockStmt blockStmt = lambdaExpr.getBody().asBlockStmt();
-        assertEquals(true, blockStmt.getStatements().isEmpty());
-    }
-
-    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition has parameters with non-null type")
-    public void thenLambdaInStatementInMethodInClassHasParametersWithNonNullType(int statementPosition, int methodPosition, int classPosition) {
-        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        for (Parameter parameter : lambdaExpr.getParameters()) {
-            assertThat(parameter.getType(), is(notNullValue()));
-        }
-    }
-
-    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition block statement is \"$expectedBody\"")
-    public void thenLambdaInStatementInMethodInClassBlockStatement(int statementPosition, int methodPosition, int classPosition,
-                                                                   String expectedBody) {
-        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        BlockStmt blockStmt = lambdaExpr.getBody().asBlockStmt();
-        Statement lambdaStmt = blockStmt.getStatement(0);
-        assertThat(lambdaStmt.toString(), is(expectedBody));
-    }
-
-    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition is parent of contained body")
-    public void thenLambdaInStatementInMethodInClassIsParentOfContainedBody(int statementPosition, int methodPosition, int classPosition) {
-        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        Statement body = lambdaExpr.getBody();
-        assertThat(body.getParentNode().get(), is(lambdaExpr));
-    }
-
-    @Then("lambda in statement $statementPosition in method $methodPosition in class $classPosition is parent of contained parameter")
-    public void thenLambdaInStatementInMethodInClassIsParentOfContainedParameter(int statementPosition, int methodPosition, int classPosition) {
-        LambdaExpr lambdaExpr = getLambdaExprInStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        Parameter parameter = lambdaExpr.getParameter(0);
-        assertThat(parameter.getParentNode().get(), is(lambdaExpr));
-    }
-
-    @Then("method reference in statement $statementPosition in method $methodPosition in class $classPosition scope is $expectedName")
-    public void thenMethodReferenceInStatementInMethodInClassIsScope(int statementPosition, int methodPosition,
-                                                                     int classPosition, String expectedName) {
-        ExpressionStmt statementUnderTest = getStatementInMethodInClass(statementPosition, methodPosition, classPosition).asExpressionStmt();
-        assertEquals(1, statementUnderTest.findAll(MethodReferenceExpr.class).size());
-        MethodReferenceExpr methodReferenceUnderTest = statementUnderTest.findFirst(MethodReferenceExpr.class).get();
-        assertThat(methodReferenceUnderTest.getScope().toString(), is(expectedName));
-    }
-
-    @Then("method reference in statement $statementPosition in method $methodPosition in class $classPosition identifier is $expectedName")
-    public void thenMethodReferenceInStatementInMethodInClassIdentifierIsCompareByAge(int statementPosition, int methodPosition,
-                                                                                      int classPosition, String expectedName) {
-        Statement statementUnderTest = getStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        assertEquals(1, statementUnderTest.findAll(MethodReferenceExpr.class).size());
-        MethodReferenceExpr methodReferenceUnderTest = statementUnderTest.findFirst(MethodReferenceExpr.class).get();
-        assertThat(methodReferenceUnderTest.getIdentifier(), is(expectedName));
-    }
-
-    @Then("method $methodPosition class $classPosition is a default method")
-    public void thenMethodClassIsADefaultMethod(int methodPosition, int classPosition) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration methodUnderTest = getMethodByPositionAndClassPosition(compilationUnit,
-                methodPosition, classPosition);
-        assertThat(methodUnderTest.isDefault(), is(true));
-    }
-
-    @Then("method $methodPosition class $classPosition is not a default method")
-    public void thenMethodClassIsNotADefaultMethod(int methodPosition, int classPosition) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration methodUnderTest = getMethodByPositionAndClassPosition(compilationUnit,
-                methodPosition, classPosition);
-        assertThat(methodUnderTest.isDefault(), is(false));
-    }
-
-    private Statement getStatementInMethodInClass(int statementPosition, int methodPosition, int classPosition) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        MethodDeclaration method = getMethodByPositionAndClassPosition(compilationUnit, methodPosition, classPosition);
-        return method.getBody().get().getStatement(statementPosition - 1);
-    }
-
-    private LambdaExpr getLambdaExprInStatementInMethodInClass(int statementPosition, int methodPosition, int classPosition) {
-        Statement statement = getStatementInMethodInClass(statementPosition, methodPosition, classPosition);
-        VariableDeclarationExpr expression = ((ExpressionStmt) statement).getExpression().asVariableDeclarationExpr();
-        VariableDeclarator variableDeclarator = expression.getVariable(0);
-        return (LambdaExpr) variableDeclarator.getInitializer().orElse(null);
-    }
-
-    @Then("all nodes refer to their parent")
-    public void allNodesReferToTheirParent() {
-        assertAllNodesOfTheCompilationUnitHaveTheirParentSet("cu1");
-    }
-
-    @Then("all nodes of the second compilation unit refer to their parent")
-    public void thenAllNodesOfTheSecondCompilationUnitReferToTheirParent() {
-        assertAllNodesOfTheCompilationUnitHaveTheirParentSet("cu2");
-    }
-
-    private void assertAllNodesOfTheCompilationUnitHaveTheirParentSet(String stateKey) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get(stateKey);
-        ExistenceOfParentNodeVerifier parentVerifier = new ExistenceOfParentNodeVerifier();
-        parentVerifier.verify(compilationUnit);
-    }
-
-    @Then("ThenExpr in the conditional expression of the statement $statementPosition in method $methodPosition in class $classPosition is LambdaExpr")
-    public void thenLambdaInConditionalExpressionInMethodInClassIsParentOfContainedParameter(int statementPosition, int methodPosition, int classPosition) {
-        ReturnStmt returnStmt = getStatementInMethodInClass(statementPosition, methodPosition, classPosition).asReturnStmt();
-        ConditionalExpr conditionalExpr = (ConditionalExpr) returnStmt.getExpression().orElse(null);
-        assertThat(conditionalExpr.getElseExpr().getClass().getName(), is(LambdaExpr.class.getName()));
-    }
-
-    @Then("the begin line is $line")
-    public void thenTheBeginLineIs(int line) {
-        Node node = (Node) state.get("selectedNode");
-        assertEquals(line, node.getBegin().get().line);
-    }
-
-    @Then("the begin column is $column")
-    public void thenTheBeginColumnIs(int column) {
-        Node node = (Node) state.get("selectedNode");
-        assertEquals(column, node.getBegin().get().column);
-    }
-
-    @Then("the end line is $line")
-    public void thenTheEndLineIs(int line) {
-        Node node = (Node) state.get("selectedNode");
-        assertEquals(line, node.getEnd().get().line);
-    }
-
-    @Then("the end column is $column")
-    public void thenTheEndColumnIs(int column) {
-        Node node = (Node) state.get("selectedNode");
-        assertEquals(column, node.getEnd().get().column);
-    }
-
-    @Then("no errors are reported")
-    public void thenNoErrorsAreReported() {
-        // this is present just for readability in the scenario specification
-        // if the code is not parsed then exceptions are thrown before reaching this step
-    }
-
-    @Then("the package name is $package")
-    public void thenThePackageNameIs(String expected) {
-        PackageDeclaration node = (PackageDeclaration) state.get("selectedNode");
-        assertEquals(expected, node.getNameAsString());
-        assertEquals(expected, node.getName().toString());
-    }
-
-    @Then("the type's diamond operator flag should be $expectedValue")
-    public void thenTheUsesDiamondOperatorShouldBeBooleanAsString(boolean expectedValue) {
-        ObjectCreationExpr expr = (ObjectCreationExpr) state.get("selectedNode");
-        assertEquals(expectedValue, expr.getType().isUsingDiamondOperator());
-    }
-
-    @Then("the Java parser cannot parse it because of an error")
-    public void javaParserCannotParseBecauseOfLexicalErrors() {
-        ParseResult<CompilationUnit> result = new JavaParser().parse(COMPILATION_UNIT, provider(sourceUnderTest));
-        if (result.isSuccessful()) {
-            fail("Lexical error expected");
-        }
-    }
-
-    @Then("the assignExpr produced doesn't have a null target")
-    public void thenTheAssignExprProducedDoesntHaveANullTarget() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        ClassOrInterfaceDeclaration classDeclaration = compilationUnit.getType(0).asClassOrInterfaceDeclaration();
-        ConstructorDeclaration ctor = classDeclaration.getMember(1).asConstructorDeclaration();
-        ExpressionStmt assignStmt = ctor.getBody().getStatement(0).asExpressionStmt();
-        AssignExpr assignExpr = assignStmt.getExpression().asAssignExpr();
-        assertNotNull(assignExpr.getTarget());
-        assertEquals(NameExpr.class, assignExpr.getTarget().getClass());
-        assertEquals(assignExpr.getTarget().asNameExpr().getNameAsString(), "mString");
-    }
-
-    private void setSelectedNodeFromCompilationUnit(Class<? extends Node> nodeType) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        List<? extends Node> nodes = compilationUnit.findAll(nodeType);
-        if (nodes.size() != 1) {
-            throw new RuntimeException(format("Exactly one %s expected", nodeType.getSimpleName()));
-        }
-        state.put("selectedNode", nodes.get(0));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/PositionRangeSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/PositionRangeSteps.java
deleted file mode 100644
index 0d7fd89..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/PositionRangeSteps.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.Position;
-import com.github.javaparser.Range;
-import org.jbehave.core.annotations.BeforeScenario;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-import org.jbehave.core.annotations.When;
-
-import static com.github.javaparser.Position.pos;
-import static com.github.javaparser.Range.range;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class PositionRangeSteps {
-
-    private Position position;
-    private Position secondPosition;
-    private Range range;
-    private Range secondRange;
-
-    @BeforeScenario
-    public void reset() {
-        position = null;
-        secondPosition = null;
-        range = null;
-        secondRange = null;
-    }
-    /*
-	 * Given steps
-     */
-
-    @Given("the position $line, $column")
-    public void givenThePosition(int line, int column) {
-        this.position = pos(line, column);
-    }
-
-    @Given("the range $line1, $column1 - $line2, $column2")
-    public void givenTheRange(int line1, int column1, int line2, int column2) {
-        this.range = range(line1, column1, line2, column2);
-    }
-
-    /*
-	 * When steps
-     */
-
-    @When("I compare to position $line, $column")
-    public void iCompareToPosition(int line, int column) {
-        secondPosition = pos(line, column);
-    }
-
-    @When("I compare to range $line1, $column1 - $line2, $column2")
-    public void whenICompareToRange(int line1, int column1, int line2, int column2) {
-        this.secondRange = range(line1, column1, line2, column2);
-    }
-
-    /*
-	 * Then steps
-     */
-
-    @Then("the positions are equal")
-    public void thenThePositionsAreEqual() {
-        assertTrue(position.equals(secondPosition));
-    }
-
-    @Then("it is after the {first|} position")
-    public void thenItIsAfterTheFirstPosition() {
-        if (secondPosition != null) {
-            assertTrue(secondPosition.isAfter(position));
-        } else {
-            assertTrue(secondRange.isAfter(position));
-        }
-    }
-
-    @Then("it is before the {first|} position")
-    public void thenItIsBeforeTheFirstPosition() {
-        if (secondPosition != null) {
-            assertTrue(secondPosition.isBefore(position));
-        } else {
-            assertTrue(secondRange.isBefore(position));
-        }
-    }
-
-    @Then("the positions are not equal")
-    public void thenThePositionsAreNotEqual() {
-        assertFalse(position.equals(secondPosition));
-    }
-
-    @Then("it is not after the {first|} position")
-    public void thenItIsNotAfterTheFirstPosition() {
-        assertFalse(secondPosition.isAfter(position));
-    }
-
-    @Then("it is not before the {first|} position")
-    public void thenItIsNotBeforeTheFirstPosition() {
-        assertFalse(secondPosition.isBefore(position));
-    }
-
-    @Then("the ranges are equal")
-    public void theRangesAreEqual() {
-        assertTrue(range.equals(secondRange));
-    }
-
-    @Then("it is contained in the first range")
-    public void itIsContainedInTheFirstRange() {
-        assertTrue(range.contains(secondRange));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/PrettyPrintingSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/PrettyPrintingSteps.java
deleted file mode 100644
index 1dcd802..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/PrettyPrintingSteps.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.visitor.ModifierVisitor;
-import com.github.javaparser.printer.PrettyPrinterConfiguration;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-import org.jbehave.core.annotations.When;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-import static com.github.javaparser.JavaParser.*;
-import static com.github.javaparser.utils.Utils.readerToString;
-import static org.junit.Assert.assertEquals;
-
-public class PrettyPrintingSteps {
-
-    private Node resultNode;
-    private String sourceUnderTest;
-
-    @Given("the {class|compilation unit|expression|block|statement|import|annotation|body|class body|interface body}:$classSrc")
-    public void givenTheClass(String classSrc) {
-        this.sourceUnderTest = classSrc.trim();
-    }
-
-    @Given("the {class|compilation unit|expression|block|statement|import|annotation|body|class body|interface body} in the file \"$classFile\"")
-    public void givenTheClassInTheFile(String classFile) throws URISyntaxException, IOException, ParseException {
-        URL url = getClass().getResource("../samples/" + classFile);
-        sourceUnderTest = readerToString(new FileReader(new File(url.toURI()))).trim();
-    }
-
-    @When("the {class|compilation unit} is parsed by the Java parser")
-    public void whenTheClassIsParsedByTheJavaParser() {
-        resultNode = parse(sourceUnderTest);
-    }
-
-    @When("the expression is parsed by the Java parser")
-    public void whenTheExpressionIsParsedByTheJavaParser() {
-        resultNode = parseExpression(sourceUnderTest);
-    }
-
-    @When("the block is parsed by the Java parser")
-    public void whenTheBlockIsParsedByTheJavaParser() {
-        resultNode = parseBlock(sourceUnderTest);
-    }
-
-    @When("the statement is parsed by the Java parser")
-    public void whenTheStatementIsParsedByTheJavaParser() {
-        resultNode = parseStatement(sourceUnderTest);
-    }
-
-    @When("the import is parsed by the Java parser")
-    public void whenTheImportIsParsedByTheJavaParser() {
-        resultNode = parseImport(sourceUnderTest);
-    }
-
-    @When("the annotation is parsed by the Java parser")
-    public void whenTheAnnotationIsParsedByTheJavaParser() {
-        resultNode = parseAnnotation(sourceUnderTest);
-    }
-
-    @When("the annotation body declaration is parsed by the Java parser")
-    public void whenTheBodyDeclarationIsParsedByTheJavaParser() {
-        resultNode = parseAnnotationBodyDeclaration(sourceUnderTest);
-    }
-
-    @When("the class body declaration is parsed by the Java parser")
-    public void whenTheClassBodyDeclarationIsParsedByTheJavaParser() {
-        resultNode = parseBodyDeclaration(sourceUnderTest);
-    }
-
-    @When("the interface body declaration is parsed by the Java parser")
-    public void whenTheInterfaceBodyDeclarationIsParsedByTheJavaParser() {
-        resultNode = parseBodyDeclaration(sourceUnderTest);
-    }
-
-    @When("the class is visited by an empty ModifierVisitorAdapter")
-    public void whenTheClassIsVisitedByAnEmptyModifierVisitorAdapter() {
-        (new ModifierVisitor<Void>() {
-        }).visit((CompilationUnit) resultNode, null);
-    }
-
-    @Then("it is printed as:$src")
-    public void isPrintedAs(String src) {
-        assertEquals(src.trim(), resultNode.toString().trim());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/SharedSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/SharedSteps.java
deleted file mode 100644
index 53b7c44..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/SharedSteps.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.BodyDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.TypeDeclaration;
-import org.hamcrest.CoreMatchers;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-import org.jbehave.core.annotations.When;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Map;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace;
-import static org.junit.Assert.assertThat;
-
-public class SharedSteps {
-
-    /* Map that maintains shares state across step classes.  If manipulating the objects in the map you must update the state */
-    private Map<String, Object> state;
-
-    public SharedSteps(Map<String, Object> state) {
-        this.state = state;
-    }
-
-    /*
-     * Given steps
-     */
-
-    @Given("a CompilationUnit")
-    public void givenACompilationUnit() {
-        state.put("cu1", new CompilationUnit());
-    }
-
-    @Given("a second CompilationUnit")
-    public void givenASecondCompilationUnit() {
-        state.put("cu2", new CompilationUnit());
-    }
-
-    /*
-     * When steps
-     */
-
-    @When("the following source is parsed:$classSrc")
-    public void whenTheFollowingSourceIsParsed(String classSrc) {
-        state.put("cu1", JavaParser.parse(classSrc.trim()));
-    }
-
-    @When("the following source is parsed (trimming space):$classSrc")
-    public void whenTheFollowingSourceIsParsedTrimmingSpace(String classSrc) {
-        state.put("cu1", JavaParser.parse(classSrc.trim()));
-    }
-
-    @When("the following sources is parsed by the second CompilationUnit:$classSrc")
-    public void whenTheFollowingSourcesIsParsedBytTheSecondCompilationUnit(String classSrc) {
-        state.put("cu2", JavaParser.parse(classSrc.trim()));
-    }
-
-    @When("file \"$fileName\" is parsed")
-    public void whenTheJavaFileIsParsed(String fileName) throws IOException, URISyntaxException {
-        URL url = getClass().getResource("../samples/" + fileName);
-        CompilationUnit compilationUnit = JavaParser.parse(new File(url.toURI()));
-        state.put("cu1", compilationUnit);
-    }
-
-    @Then("the CompilationUnit is equal to the second CompilationUnit")
-    public void thenTheCompilationUnitIsEqualToTheSecondCompilationUnit() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
-
-        assertThat(compilationUnit, is(equalTo(compilationUnit2)));
-    }
-
-    @Then("the CompilationUnit has the same hashcode to the second CompilationUnit")
-    public void thenTheCompilationUnitHasTheSameHashcodeToTheSecondCompilationUnit() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
-
-        assertThat(compilationUnit.hashCode(), is(equalTo(compilationUnit2.hashCode())));
-    }
-
-    @Then("the CompilationUnit is not equal to the second CompilationUnit")
-    public void thenTheCompilationUnitIsNotEqualToTheSecondCompilationUnit() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
-
-        assertThat(compilationUnit, not(equalTo(compilationUnit2)));
-    }
-
-    @Then("the CompilationUnit has a different hashcode to the second CompilationUnit")
-    public void thenTheCompilationUnitHasADifferentHashcodeToTheSecondCompilationUnit() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        CompilationUnit compilationUnit2 = (CompilationUnit) state.get("cu2");
-
-        assertThat(compilationUnit.hashCode(), not(equalTo(compilationUnit2.hashCode())));
-    }
-
-    @Then("the expected source should be:$classSrc")
-    public void thenTheExpectedSourcesShouldBe(String classSrc) {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        assertThat(compilationUnit.toString(), CoreMatchers.is(equalToIgnoringWhiteSpace(classSrc)));
-    }
-
-    public static <T extends BodyDeclaration<?>> T getMemberByTypeAndPosition(TypeDeclaration<?> typeDeclaration, int position, Class<T> typeClass) {
-        int typeCount = 0;
-        for (BodyDeclaration<?> declaration : typeDeclaration.getMembers()) {
-            if (declaration.getClass().equals(typeClass)) {
-                if (typeCount == position) {
-                    return (T) declaration;
-                }
-                typeCount++;
-            }
-        }
-        throw new IllegalArgumentException("No member " + typeClass + " at position: " + position);
-    }
-
-    public static MethodDeclaration getMethodByPositionAndClassPosition(CompilationUnit compilationUnit,
-                                                                        int methodPosition, int classPosition) {
-        TypeDeclaration<?> type = compilationUnit.getType(classPosition - 1);
-
-        int memberCount = 0;
-        int methodCount = 0;
-        for (BodyDeclaration<?> bodyDeclaration : type.getMembers()) {
-            if (bodyDeclaration instanceof MethodDeclaration) {
-                if (methodCount == methodPosition - 1) {
-                    return (MethodDeclaration) type.getMember(memberCount);
-                }
-                methodCount++;
-            }
-            memberCount++;
-        }
-        throw new IllegalArgumentException("Method not found at position " + methodPosition + "in class " + classPosition);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/VisitorSteps.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/VisitorSteps.java
deleted file mode 100644
index ba20eaf..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/steps/VisitorSteps.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.bdd.steps;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.visitor.CloneVisitor;
-import com.github.javaparser.ast.visitor.GenericListVisitorAdapter;
-import com.github.javaparser.ast.visitor.GenericVisitorAdapter;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
-import com.github.javaparser.bdd.visitors.PositionTestVisitor;
-import org.jbehave.core.annotations.Given;
-import org.jbehave.core.annotations.Then;
-import org.jbehave.core.annotations.When;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-public class VisitorSteps {
-
-    /* Fields used to maintain step state within this step class */
-    private VoidVisitorAdapter<AtomicReference<String>> toUpperCaseVariableNameVisitor;
-    private VoidVisitorAdapter<AtomicReference<String>> collectVariableNameVisitor;
-    private PositionTestVisitor positionTestVisitor;
-    private GenericVisitorAdapter<String, Void> nameReturningVisitor;
-    private GenericListVisitorAdapter<String, Void> allNameReturningVisitor;
-    private AtomicReference<String> collectedVariableName;
-    private String returnedVariableName;
-    private List<String> returnedVariableNames;
-
-    /* Map that maintains shares state across step classes.  If manipulating the objects in the map you must update the state */
-    private Map<String, Object> state;
-
-    public VisitorSteps(Map<String, Object> state) {
-        this.state = state;
-    }
-
-    @Given("a VoidVisitorAdapter with a visit method that changes variable names to uppercase")
-    public void givenAVoidVisitorAdapterWithAVisitMethodThatChangesVariableNamesToUppercase() {
-        toUpperCaseVariableNameVisitor = new VoidVisitorAdapter<AtomicReference<String>>() {
-            @Override
-            public void visit(VariableDeclarator n, AtomicReference<String> arg) {
-                n.setName(n.getNameAsString().toUpperCase());
-            }
-        };
-    }
-
-    @Given("a VoidVisitorAdapter with a visit method and collects the variable names")
-    public void givenAVoidVisitorAdapterWithAVisitMethodThatCollectsTheVariableName() {
-        collectVariableNameVisitor = new VoidVisitorAdapter<AtomicReference<String>>() {
-            @Override
-            public void visit(VariableDeclarator n, AtomicReference<String> arg) {
-                arg.set(arg.get() + n.getName() + ";");
-            }
-
-            @Override
-            public void visit(Parameter n, AtomicReference<String> arg) {
-                arg.set(arg.get() + n.getName() + ";");
-            }
-        };
-    }
-
-    @Given("a GenericVisitorAdapter with a visit method that returns variable names")
-    public void givenAGenericVisitorAdapterWithAVisitMethodThatReturnsVariableNames() {
-        nameReturningVisitor = new GenericVisitorAdapter<String, Void>() {
-            @Override
-            public String visit(VariableDeclarator n, Void arg) {
-                return n.getNameAsString();
-            }
-        };
-    }
-
-    @Given("a GenericListVisitorAdapter with a visit method that returns all variable names")
-    public void givenAGenericListVisitorAdapterWithAVisitMethodThatReturnsAllVariableNames() {
-        allNameReturningVisitor = new GenericListVisitorAdapter<String, Void>() {
-            @Override
-            public List<String> visit(VariableDeclarator n, Void arg) {
-                return Collections.singletonList(n.getNameAsString());
-            }
-        };
-    }
-
-    @Given("a VoidVisitorAdapter with a visit method that asserts sensible line positions")
-    public void givenAVoidVisitorAdapterWithAVisitMethodThatAssertsSensibleLinePositions() {
-        positionTestVisitor = new PositionTestVisitor();
-    }
-
-    @When("the CompilationUnit is cloned to the second CompilationUnit")
-    public void whenTheSecondCompilationUnitIsCloned() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        CompilationUnit compilationUnit2 = (CompilationUnit) compilationUnit.accept(new CloneVisitor(), null);
-        state.put("cu2", compilationUnit2);
-    }
-
-    @When("the CompilationUnit is visited by the to uppercase visitor")
-    public void whenTheCompilationUnitIsVisitedByTheVistor() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        toUpperCaseVariableNameVisitor.visit(compilationUnit, null);
-        state.put("cu1", compilationUnit);
-    }
-
-    @When("the CompilationUnit is visited by the variable name collector visitor")
-    public void whenTheCompilationUnitIsVisitedByTheVariableNameCollectorVisitor() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        collectedVariableName = new AtomicReference<>("");
-        collectVariableNameVisitor.visit(compilationUnit, collectedVariableName);
-    }
-
-    @When("the CompilationUnit is visited by the visitor that returns variable names")
-    public void whenTheCompilationUnitIsVisitedByTheVisitorThatReturnsVariableNames() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        returnedVariableName = nameReturningVisitor.visit(compilationUnit, null);
-    }
-
-    @When("the CompilationUnit is visited by the visitor that returns all variable names")
-    public void whenTheCompilationUnitIsVisitedByTheVisitorThatReturnsAllVariableNames() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        returnedVariableNames = allNameReturningVisitor.visit(compilationUnit, null);
-    }
-
-    @When("the CompilationUnit is visited by the PositionTestVisitor")
-    public void whenTheCompilationUnitIsVisitedByThePositionTestVisitor() {
-        CompilationUnit compilationUnit = (CompilationUnit) state.get("cu1");
-        compilationUnit.accept(positionTestVisitor, null);
-    }
-
-    @Then("the collected variable name is \"$nameUnderTest\"")
-    public void thenTheCollectedVariableNameIs(String nameUnderTest) {
-        assertThat(collectedVariableName.get(), is(nameUnderTest));
-    }
-
-    @Then("the return variable name is \"$nameUnderTest\"")
-    public void thenTheReturnVariableNameIs(String nameUnderTest) {
-        assertThat(returnedVariableName, is(nameUnderTest));
-    }
-
-    @Then("the first return variable name is \"$nameUnderTest\"")
-    public void thenTheFirstReturnVariableNameIs(String nameUnderTest) {
-        assertThat(returnedVariableNames.get(0), is(nameUnderTest));
-    }
-
-    @Then("the total number of nodes visited is $expectedCount")
-    public void thenTheTotalNumberOfNodesVisitedIs(int expectedCount) {
-        assertThat(positionTestVisitor.getNumberOfNodesVisited(), is(expectedCount));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/bdd/visitors/PositionTestVisitor.java b/javaparser-testing/src/test/java/com/github/javaparser/bdd/visitors/PositionTestVisitor.java
deleted file mode 100644
index bfa331f..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/bdd/visitors/PositionTestVisitor.java
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * 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.bdd.visitors;
-
-import com.github.javaparser.Position;
-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.expr.*;
-import com.github.javaparser.ast.stmt.*;
-import com.github.javaparser.ast.type.*;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.lessThanOrEqualTo;
-import static org.hamcrest.core.Is.is;
-
-public class PositionTestVisitor extends VoidVisitorAdapter<Object> {
-
-    private int numberOfNodesVisited;
-
-    @Override
-    public void visit(final AnnotationDeclaration n, final Object arg) {
-        doTest(n);
-        doTest(n.getName());
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final AnnotationMemberDeclaration n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ArrayAccessExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ArrayCreationExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ArrayInitializerExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final AssertStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final AssignExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final BinaryExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final BlockComment n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final BlockStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final BooleanLiteralExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final BreakStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final CastExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final CatchClause n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(LambdaExpr n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(MethodReferenceExpr n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(TypeExpr n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final CharLiteralExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ClassExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ClassOrInterfaceDeclaration n, final Object arg) {
-        doTest(n);
-        doTest(n.getName());
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ClassOrInterfaceType n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final CompilationUnit n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ConditionalExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ConstructorDeclaration n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ContinueStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final DoStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final DoubleLiteralExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final EmptyStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final EnclosedExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final EnumConstantDeclaration n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final EnumDeclaration n, final Object arg) {
-        doTest(n);
-        doTest(n.getName());
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ExplicitConstructorInvocationStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ExpressionStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final FieldAccessExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final FieldDeclaration n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ForeachStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ForStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final IfStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final InitializerDeclaration n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final InstanceOfExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final IntegerLiteralExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final JavadocComment n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final LabeledStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final LineComment n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final LongLiteralExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final MarkerAnnotationExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final MemberValuePair n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final MethodCallExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final MethodDeclaration n, final Object arg) {
-        doTest(n);
-        doTest(n.getName());
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final NameExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final NormalAnnotationExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final NullLiteralExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ObjectCreationExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final PackageDeclaration n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final Parameter n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final PrimitiveType n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final Name n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(SimpleName n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(ArrayType n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(ArrayCreationLevel n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final IntersectionType n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(UnionType n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ReturnStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final SingleMemberAnnotationExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final StringLiteralExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final SuperExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final SwitchEntryStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final SwitchStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final SynchronizedStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ThisExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final ThrowStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final TryStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final LocalClassDeclarationStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final TypeParameter n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final UnaryExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final VariableDeclarationExpr n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final VariableDeclarator n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final VoidType n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final WhileStmt n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(final WildcardType n, final Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    @Override
-    public void visit(UnknownType n, Object arg) {
-        doTest(n);
-        super.visit(n, arg);
-    }
-
-    private void doTest(final Node node) {
-        Position begin = node.getRange().get().begin;
-        Position end = node.getRange().get().end;
-        assertThat(begin.line, is(greaterThanOrEqualTo(0)));
-        assertThat(begin.column, is(greaterThanOrEqualTo(0)));
-        assertThat(end.line, is(greaterThanOrEqualTo(0)));
-        assertThat(end.column, is(greaterThanOrEqualTo(0)));
-
-        if (begin.line == end.line) {
-            assertThat(begin.column, is(lessThanOrEqualTo(end.column)));
-        } else {
-            assertThat(begin.line, is(lessThanOrEqualTo(end.line)));
-        }
-        numberOfNodesVisited++;
-    }
-
-    public int getNumberOfNodesVisited() {
-        return numberOfNodesVisited;
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/ClassOrInterfaceDeclarationBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/ClassOrInterfaceDeclarationBuildersTest.java
deleted file mode 100644
index aff5354..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/ClassOrInterfaceDeclarationBuildersTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.builders;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.List;
-import java.util.function.Function;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class ClassOrInterfaceDeclarationBuildersTest {
-    CompilationUnit cu;
-
-    @Before
-    public void setup() {
-        cu = new CompilationUnit();
-    }
-
-    @After
-    public void teardown() {
-        cu = null;
-    }
-
-    @Test
-    public void testAddExtends() {
-        ClassOrInterfaceDeclaration testClass = cu.addClass("test");
-        testClass.addExtendedType(List.class);
-        assertEquals(1, cu.getImports().size());
-        assertEquals("import " + List.class.getName() + ";" + EOL,
-                cu.getImport(0).toString());
-        assertEquals(1, testClass.getExtendedTypes().size());
-        assertEquals(List.class.getSimpleName(), testClass.getExtendedTypes(0).getNameAsString());
-    }
-
-    @Test
-    public void testAddImplements() {
-        ClassOrInterfaceDeclaration testClass = cu.addClass("test");
-        testClass.addImplementedType(Function.class);
-        assertEquals(1, cu.getImports().size());
-        assertEquals("import " + Function.class.getName() + ";" + EOL,
-                cu.getImport(0).toString());
-        assertEquals(1, testClass.getImplementedTypes().size());
-        assertEquals(Function.class.getSimpleName(), testClass.getImplementedTypes(0).getNameAsString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/CompilationUnitBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/CompilationUnitBuildersTest.java
deleted file mode 100644
index 11ac7e9..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/CompilationUnitBuildersTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.builders;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-import java.util.Map;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.AnnotationDeclaration;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.EnumDeclaration;
-
-public class CompilationUnitBuildersTest {
-    private final CompilationUnit cu = new CompilationUnit();
-
-    @Test
-    public void testAddImport() {
-        cu.addImport(Map.class);
-        cu.addImport(Map.class);
-        cu.addImport(List.class);
-        assertEquals(2, cu.getImports().size());
-        cu.addImport("myImport");
-        assertEquals(3, cu.getImports().size());
-        assertEquals("import " + Map.class.getName() + ";" + EOL, cu.getImport(0).toString());
-        assertEquals("import " + List.class.getName() + ";" + EOL, cu.getImport(1).toString());
-        assertEquals("import myImport;" + EOL, cu.getImport(2).toString());
-    }
-
-    class testInnerClass {
-
-    }
-
-    @Test
-    public void testAddImportAnonymousClass() {
-        cu.addImport(testInnerClass.class);
-        assertEquals("import " + testInnerClass.class.getName().replace("$", ".") + ";" + EOL,
-                cu.getImport(0).toString());
-    }
-
-    @Test(expected = RuntimeException.class)
-    public void testAddImportInnerClass() {
-        Object anonymous = new Object() {
-
-        };
-        cu.addImport(anonymous.getClass());
-    }
-
-    @Test
-    public void testAddClass() {
-        ClassOrInterfaceDeclaration myClassDeclaration = cu.addClass("testClass", Modifier.PRIVATE);
-        assertEquals(1, cu.getTypes().size());
-        assertEquals("testClass", cu.getType(0).getNameAsString());
-        assertEquals(ClassOrInterfaceDeclaration.class, cu.getType(0).getClass());
-        assertTrue(myClassDeclaration.isPrivate());
-        assertFalse(myClassDeclaration.isInterface());
-    }
-
-    @Test
-    public void testAddInterface() {
-        ClassOrInterfaceDeclaration myInterfaceDeclaration = cu.addInterface("testInterface");
-        assertEquals(1, cu.getTypes().size());
-        assertEquals("testInterface", cu.getType(0).getNameAsString());
-        assertTrue(myInterfaceDeclaration.isPublic());
-        assertEquals(ClassOrInterfaceDeclaration.class, cu.getType(0).getClass());
-        assertTrue(myInterfaceDeclaration.isInterface());
-    }
-
-    @Test
-    public void testAddEnum() {
-        EnumDeclaration myEnumDeclaration = cu.addEnum("test");
-        assertEquals(1, cu.getTypes().size());
-        assertEquals("test", cu.getType(0).getNameAsString());
-        assertTrue(myEnumDeclaration.isPublic());
-        assertEquals(EnumDeclaration.class, cu.getType(0).getClass());
-    }
-
-    @Test
-    public void testAddAnnotationDeclaration() {
-        AnnotationDeclaration myAnnotationDeclaration = cu.addAnnotationDeclaration("test");
-        assertEquals(1, cu.getTypes().size());
-        assertEquals("test", cu.getType(0).getNameAsString());
-        assertTrue(myAnnotationDeclaration.isPublic());
-        assertEquals(AnnotationDeclaration.class, cu.getType(0).getClass());
-    }
-
-    @Test
-    public void testGetClassByName() {
-        assertEquals(cu.addClass("test"), cu.getClassByName("test").get());
-    }
-
-    @Test
-    public void testGetInterfaceByName() {
-        assertEquals(cu.addInterface("test"), cu.getInterfaceByName("test").get());
-    }
-
-    @Test
-    public void testGetEnumByName() {
-        assertEquals(cu.addEnum("test"), cu.getEnumByName("test").get());
-    }
-
-    @Test
-    public void testGetAnnotationDeclarationByName() {
-        assertEquals(cu.addAnnotationDeclaration("test"), cu.getAnnotationDeclarationByName("test").get());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/EnumDeclarationBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/EnumDeclarationBuildersTest.java
deleted file mode 100644
index 048307d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/EnumDeclarationBuildersTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.builders;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.EnumDeclaration;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.function.Function;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class EnumDeclarationBuildersTest {
-    private final CompilationUnit cu = new CompilationUnit();
-
-    @Test
-    public void testAddImplements() {
-        EnumDeclaration testEnum = cu.addEnum("test");
-        testEnum.addImplementedType(Function.class);
-        assertEquals(1, cu.getImports().size());
-        assertEquals("import " + Function.class.getName() + ";" + EOL,
-                cu.getImport(0).toString());
-        assertEquals(1, testEnum.getImplementedTypes().size());
-        assertEquals(Function.class.getSimpleName(), testEnum.getImplementedTypes(0).getNameAsString());
-    }
-
-    @Test
-    public void testAddEnumConstant() {
-        EnumDeclaration testEnum = cu.addEnum("test");
-        testEnum.addEnumConstant("MY_ENUM_CONSTANT");
-        assertEquals(1, testEnum.getEntries().size());
-        assertEquals("MY_ENUM_CONSTANT", testEnum.getEntry(0).getNameAsString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/FieldDeclarationBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/FieldDeclarationBuildersTest.java
deleted file mode 100644
index 7824add..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/FieldDeclarationBuildersTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.builders;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.ast.stmt.ReturnStmt;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.List;
-
-import static com.github.javaparser.ast.type.PrimitiveType.intType;
-import static org.junit.Assert.assertEquals;
-
-public class FieldDeclarationBuildersTest {
-    private final CompilationUnit cu = new CompilationUnit();
-    private ClassOrInterfaceDeclaration testClass = cu.addClass("testClass");
-    private EnumDeclaration testEnum = cu.addEnum("testEnum");
-
-    @Test(expected = IllegalStateException.class)
-    public void testOrphanFieldGetter() {
-        new FieldDeclaration().createGetter();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testOrphanFieldSetter() {
-        new FieldDeclaration().createSetter();
-    }
-
-    @Test
-    public void testCreateGetterInAClass() {
-        testClass.addPrivateField(int.class, "myField").createGetter();
-        assertEquals(2, testClass.getMembers().size());
-        assertEquals(MethodDeclaration.class, testClass.getMember(1).getClass());
-        List<MethodDeclaration> methodsWithName = testClass.getMethodsByName("getMyField");
-        assertEquals(1, methodsWithName.size());
-        MethodDeclaration getter = methodsWithName.get(0);
-        assertEquals("getMyField", getter.getNameAsString());
-        assertEquals("int", getter.getType().toString());
-        assertEquals(ReturnStmt.class, getter.getBody().get().getStatement(0).getClass());
-    }
-
-    @Test
-    public void testCreateSetterInAClass() {
-        testClass.addPrivateField(int.class, "myField").createSetter();
-        assertEquals(2, testClass.getMembers().size());
-        assertEquals(MethodDeclaration.class, testClass.getMember(1).getClass());
-        List<MethodDeclaration> methodsWithName = testClass.getMethodsByName("setMyField");
-        assertEquals(1, methodsWithName.size());
-        MethodDeclaration setter = methodsWithName.get(0);
-        assertEquals("setMyField", setter.getNameAsString());
-        assertEquals("int", setter.getParameter(0).getType().toString());
-        assertEquals(ExpressionStmt.class, setter.getBody().get().getStatement(0).getClass());
-        assertEquals("this.myField = myField;", setter.getBody().get().getStatement(0).toString());
-    }
-
-    @Test
-    public void testCreateGetterInEnum() {
-        testEnum.addPrivateField(int.class, "myField").createGetter();
-        assertEquals(2, testEnum.getMembers().size());
-        assertEquals(MethodDeclaration.class, testEnum.getMember(1).getClass());
-        List<MethodDeclaration> methodsWithName = testEnum.getMethodsByName("getMyField");
-        assertEquals(1, methodsWithName.size());
-        MethodDeclaration getter = methodsWithName.get(0);
-        assertEquals("getMyField", getter.getNameAsString());
-        assertEquals("int", getter.getType().toString());
-        assertEquals(ReturnStmt.class, getter.getBody().get().getStatement(0).getClass());
-    }
-
-    @Test
-    public void testCreateSetterInEnum() {
-        testEnum.addPrivateField(int.class, "myField").createSetter();
-        assertEquals(2, testEnum.getMembers().size());
-        assertEquals(MethodDeclaration.class, testEnum.getMember(1).getClass());
-        List<MethodDeclaration> methodsWithName = testEnum.getMethodsByName("setMyField");
-        assertEquals(1, methodsWithName.size());
-        MethodDeclaration setter = methodsWithName.get(0);
-        assertEquals("setMyField", setter.getNameAsString());
-        assertEquals("int", setter.getParameter(0).getType().toString());
-        assertEquals(ExpressionStmt.class, setter.getBody().get().getStatement(0).getClass());
-        assertEquals("this.myField = myField;", setter.getBody().get().getStatement(0).toString());
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testCreateGetterWithANonValidField() {
-        FieldDeclaration myPrivateField = testClass.addPrivateField(int.class, "myField");
-        myPrivateField.getVariables().add(new VariableDeclarator(intType(), "secondField"));
-        myPrivateField.createGetter();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testCreateSetterWithANonValidField() {
-        FieldDeclaration myPrivateField = testClass.addPrivateField(int.class, "myField");
-        myPrivateField.getVariables().add(new VariableDeclarator(intType(), "secondField"));
-        myPrivateField.createSetter();
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithAnnotationsBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithAnnotationsBuildersTest.java
deleted file mode 100644
index b722016..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithAnnotationsBuildersTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.builders;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.expr.NormalAnnotationExpr;
-import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class NodeWithAnnotationsBuildersTest {
-    private CompilationUnit cu = new CompilationUnit();
-    private ClassOrInterfaceDeclaration testClass = cu.addClass("testClass"); ;
-
-    @interface hey {
-
-    }
-
-    @Test
-    public void testAddAnnotation() {
-        NormalAnnotationExpr annotation = testClass.addAndGetAnnotation(hey.class);
-        assertEquals("import com.github.javaparser.builders.NodeWithAnnotationsBuildersTest.hey;", cu.getImport(0).toString().trim());
-        assertEquals(1, testClass.getAnnotations().size());
-        assertEquals(annotation, testClass.getAnnotation(0));
-        assertEquals(NormalAnnotationExpr.class, testClass.getAnnotation(0).getClass());
-    }
-
-    @Test
-    public void testAddMarkerAnnotation() {
-        testClass.addMarkerAnnotation("test");
-        assertEquals(1, testClass.getAnnotations().size());
-    }
-
-    @Test
-    public void testAddSingleMemberAnnotation() {
-        testClass.addSingleMemberAnnotation("test", "value");
-        assertEquals(1, testClass.getAnnotations().size());
-        assertEquals("value", testClass.getAnnotation(0).asSingleMemberAnnotationExpr().getMemberValue().toString());
-    }
-
-    @Test
-    public void testIsAnnotationPresent() {
-        testClass.addMarkerAnnotation(hey.class);
-        assertTrue(testClass.isAnnotationPresent(hey.class));
-    }
-
-    @Test
-    public void testGetAnnotationByName() {
-        NormalAnnotationExpr annotation = testClass.addAndGetAnnotation(hey.class);
-        assertEquals(annotation, testClass.getAnnotationByName("hey").get());
-    }
-
-    @Test
-    public void testGetAnnotationByClass() {
-        NormalAnnotationExpr annotation = testClass.addAndGetAnnotation(hey.class);
-        assertEquals(annotation, testClass.getAnnotationByClass(hey.class).get());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithMembersBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithMembersBuildersTest.java
deleted file mode 100644
index 4ac1f06..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithMembersBuildersTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.builders;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import org.junit.Test;
-
-import java.util.List;
-
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class NodeWithMembersBuildersTest {
-    private final CompilationUnit cu = new CompilationUnit();
-    private final ClassOrInterfaceDeclaration classDeclaration = cu.addClass("test");
-
-    @Test
-    public void testAddField() {
-        FieldDeclaration addField = classDeclaration.addField(int.class, "fieldName", Modifier.PRIVATE);
-        assertEquals(1, classDeclaration.getMembers().size());
-        assertEquals(addField, classDeclaration.getMember(0));
-        assertEquals("fieldName", addField.getVariable(0).getNameAsString());
-    }
-
-    @Test
-    public void testAddMethod() {
-        MethodDeclaration addMethod = classDeclaration.addMethod("foo", Modifier.PUBLIC);
-        assertEquals(1, classDeclaration.getMembers().size());
-        assertEquals(addMethod, classDeclaration.getMember(0));
-        assertEquals("foo", addMethod.getNameAsString());
-    }
-
-    @Test
-    public void testAddCtor() {
-        ConstructorDeclaration addCtor = classDeclaration.addConstructor(Modifier.PUBLIC);
-        assertEquals(1, classDeclaration.getMembers().size());
-        assertEquals(addCtor, classDeclaration.getMember(0));
-        assertEquals(classDeclaration.getName(), addCtor.getName());
-    }
-
-    @Test
-    public void testAddInitializers() {
-        classDeclaration.addInitializer();
-        assertEquals(1, classDeclaration.getMembers().size());
-        assertEquals(InitializerDeclaration.class, classDeclaration.getMember(0).getClass());
-
-        classDeclaration.addStaticInitializer();
-        assertEquals(2, classDeclaration.getMembers().size());
-        assertEquals(InitializerDeclaration.class, classDeclaration.getMember(0).getClass());
-    }
-
-    @Test
-    public void testGetMethodsWithName() {
-        MethodDeclaration addMethod = classDeclaration.addMethod("foo", Modifier.PUBLIC);
-        MethodDeclaration addMethod2 = classDeclaration.addMethod("foo", Modifier.PUBLIC).addParameter(int.class, "overload");
-        List<MethodDeclaration> methodsByName = classDeclaration.getMethodsByName("foo");
-        assertEquals(2, methodsByName.size());
-        assertTrue(methodsByName.contains(addMethod));
-        assertTrue(methodsByName.contains(addMethod2));
-    }
-
-    @Test
-    public void testGetMethods() {
-        MethodDeclaration addMethod = classDeclaration.addMethod("foo", Modifier.PUBLIC);
-        MethodDeclaration addMethod2 = classDeclaration.addMethod("foo", Modifier.PUBLIC).addParameter(int.class, "overload");
-
-        List<MethodDeclaration> methods = classDeclaration.getMethods();
-
-        assertEquals(2, methods.size());
-        assertTrue(methods.contains(addMethod));
-        assertTrue(methods.contains(addMethod2));
-    }
-
-    @Test
-    public void testGetMethodsWithParameterTypes() {
-        classDeclaration.addMethod("foo", Modifier.PUBLIC);
-        MethodDeclaration addMethod2 = classDeclaration.addMethod("foo", Modifier.PUBLIC).addParameter(int.class, "overload");
-        ClassOrInterfaceType type = parseClassOrInterfaceType("List");
-        type.setTypeArguments(parseClassOrInterfaceType("String"));
-        MethodDeclaration methodWithListParam = classDeclaration.addMethod("fooList", Modifier.PUBLIC).addParameter(type, "overload");
-        MethodDeclaration addMethod3 = classDeclaration.addMethod("foo2", Modifier.PUBLIC).addParameter(int.class, "overload");
-
-        List<MethodDeclaration> methodsByParam = classDeclaration.getMethodsByParameterTypes(int.class);
-        assertEquals(2, methodsByParam.size());
-        assertTrue(methodsByParam.contains(addMethod2));
-        assertTrue(methodsByParam.contains(addMethod3));
-        List<MethodDeclaration> methodsByParam2 = classDeclaration.getMethodsByParameterTypes("List<String>");
-        assertEquals(1, methodsByParam2.size());
-        assertTrue(methodsByParam2.contains(methodWithListParam));
-    }
-
-    @Test
-    public void testGetFieldWithName() {
-        FieldDeclaration addField = classDeclaration.addField(int.class, "fieldName", Modifier.PRIVATE);
-        classDeclaration.addField(float.class, "secondField", Modifier.PRIVATE);
-        FieldDeclaration fieldByName = classDeclaration.getFieldByName("fieldName").get();
-        assertEquals(addField, fieldByName);
-    }
-
-    @Test
-    public void testGetFields() {
-        FieldDeclaration firstField = classDeclaration.addField(int.class, "fieldName", Modifier.PRIVATE);
-        FieldDeclaration secondField = classDeclaration.addField(float.class, "secondField", Modifier.PRIVATE);
-
-        List<FieldDeclaration> fields = classDeclaration.getFields();
-
-        assertTrue(fields.contains(firstField));
-        assertTrue(fields.contains(secondField));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithParametersBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithParametersBuildersTest.java
deleted file mode 100644
index 87d0a25..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithParametersBuildersTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.builders;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.Parameter;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.List;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class NodeWithParametersBuildersTest {
-    private final CompilationUnit cu = new CompilationUnit();
-
-    @Test
-    public void testAddParameter() {
-        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", Modifier.PUBLIC);
-        addMethod.addParameter(int.class, "yay");
-        Parameter myNewParam = addMethod.addAndGetParameter(List.class, "myList");
-        assertEquals(1, cu.getImports().size());
-        assertEquals("import " + List.class.getName() + ";" + EOL, cu.getImport(0).toString());
-        assertEquals(2, addMethod.getParameters().size());
-        assertEquals("yay", addMethod.getParameter(0).getNameAsString());
-        assertEquals("List", addMethod.getParameter(1).getType().toString());
-        assertEquals(myNewParam, addMethod.getParameter(1));
-    }
-
-    @Test
-    public void testGetParamByName() {
-        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", Modifier.PUBLIC);
-        Parameter addAndGetParameter = addMethod.addAndGetParameter(int.class, "yay");
-        assertEquals(addAndGetParameter, addMethod.getParameterByName("yay").get());
-    }
-
-    @Test
-    public void testGetParamByType() {
-        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", Modifier.PUBLIC);
-        Parameter addAndGetParameter = addMethod.addAndGetParameter(int.class, "yay");
-        assertEquals(addAndGetParameter, addMethod.getParameterByType("int").get());
-        assertEquals(addAndGetParameter, addMethod.getParameterByType(int.class).get());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithThrownExceptionsBuildersTest.java b/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithThrownExceptionsBuildersTest.java
deleted file mode 100644
index 7975606..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/builders/NodeWithThrownExceptionsBuildersTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.builders;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
-import static org.junit.Assert.assertEquals;
-
-public class NodeWithThrownExceptionsBuildersTest {
-    private final CompilationUnit cu = new CompilationUnit();
-
-    @Test
-    public void testThrows() {
-        MethodDeclaration addMethod = cu.addClass("test").addMethod("foo", Modifier.PUBLIC);
-        addMethod.addThrownException(IllegalStateException.class);
-        assertEquals(1, addMethod.getThrownExceptions().size());
-        assertEquals(true, addMethod.isThrown(IllegalStateException.class));
-        addMethod.addThrownException(parseClassOrInterfaceType("Test"));
-        assertEquals(2, addMethod.getThrownExceptions().size());
-        assertEquals("Test", addMethod.getThrownException(1).toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/javadoc/JavadocExtractorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/javadoc/JavadocExtractorTest.java
deleted file mode 100644
index 59740b3..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/javadoc/JavadocExtractorTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.javadoc;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ParseProblemException;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
-import org.apache.commons.io.Charsets;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.nio.charset.StandardCharsets;
-
-public class JavadocExtractorTest {
-
-    @Test
-    public void canParseAllJavadocsInJavaParser() throws FileNotFoundException {
-        processDir(new File(".."));
-    }
-
-    private void processFile(File file) throws FileNotFoundException {
-        try {
-            CompilationUnit cu = JavaParser.parse(file, StandardCharsets.UTF_8);
-            new VoidVisitorAdapter<Object>() {
-                @Override
-                public void visit(JavadocComment n, Object arg) {
-                    super.visit(n, arg);
-                    n.parse();
-                }
-            }.visit(cu, null);
-        } catch (ParseProblemException e) {
-            System.err.println("ERROR PROCESSING "+ file);
-        }
-    }
-
-    private void processDir(File dir) throws FileNotFoundException {
-        for (File child : dir.listFiles()) {
-            if (child.isFile() && child.getName().endsWith(".java")) {
-                processFile(child);
-            } else if (child.isDirectory()) {
-                processDir(child);
-            }
-        }
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/javadoc/JavadocTest.java b/javaparser-testing/src/test/java/com/github/javaparser/javadoc/JavadocTest.java
deleted file mode 100644
index 7377dfb..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/javadoc/JavadocTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.javadoc;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.javadoc.description.JavadocDescription;
-import com.github.javaparser.javadoc.description.JavadocDescriptionElement;
-import com.github.javaparser.javadoc.description.JavadocInlineTag;
-import org.junit.Test;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class JavadocTest {
-
-    @Test
-    public void toTextForEmptyJavadoc() {
-        Javadoc javadoc = new Javadoc(new JavadocDescription());
-        assertEquals("", javadoc.toText());
-    }
-
-    @Test
-    public void toTextForJavadocWithTwoLinesOfJustDescription() {
-        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
-        assertEquals("first line" + EOL + "second line" + EOL, javadoc.toText());
-    }
-
-    @Test
-    public void toTextForJavadocWithTwoLinesOfJustDescriptionAndOneBlockTag() {
-        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
-        javadoc.addBlockTag("foo", "something useful");
-        assertEquals("first line" + EOL + "second line" + EOL + EOL + "@foo something useful" + EOL, javadoc.toText());
-    }
-
-    @Test
-    public void toCommentForEmptyJavadoc() {
-        Javadoc javadoc = new Javadoc(new JavadocDescription());
-        assertEquals(new JavadocComment("" + EOL + "\t\t "), javadoc.toComment("\t\t"));
-    }
-
-    @Test
-    public void toCommentorJavadocWithTwoLinesOfJustDescription() {
-        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
-        assertEquals(new JavadocComment("" + EOL + "\t\t * first line" + EOL + "\t\t * second line" + EOL + "\t\t "), javadoc.toComment("\t\t"));
-    }
-
-    @Test
-    public void toCommentForJavadocWithTwoLinesOfJustDescriptionAndOneBlockTag() {
-        Javadoc javadoc = new Javadoc(JavadocDescription.parseText("first line" + EOL + "second line"));
-        javadoc.addBlockTag("foo", "something useful");
-        assertEquals(new JavadocComment("" + EOL + "\t\t * first line" + EOL + "\t\t * second line" + EOL + "\t\t * " + EOL + "\t\t * @foo something useful" + EOL + "\t\t "), javadoc.toComment("\t\t"));
-    }
-
-    @Test
-    public void descriptionAndBlockTagsAreRetrievable() {
-        Javadoc javadoc = JavaParser.parseJavadoc("first line" + EOL + "second line" + EOL + EOL + "@param node a node" + EOL + "@return result the result");
-        assertEquals("first line" + EOL + "second line", javadoc.getDescription().toText());
-        assertEquals(2, javadoc.getBlockTags().size());
-    }
-
-    @Test
-    public void inlineTagsAreParsable() {
-        String docText =
-                "Returns the {@link TOFilename}s of all files that existed during the requested" + EOL +
-                        "{@link TOVersion}." + EOL +
-                        "" + EOL +
-                        "@param versionID the id of the {@link TOVersion}." + EOL +
-                        "@return the filenames" + EOL +
-                        "@throws InvalidIDException if the {@link IPersistence} doesn't recognize the given versionID." + EOL;
-        String javadoc = JavaParser.parseJavadoc(docText).toText();
-        assertTrue(javadoc.contains("{@link TOVersion}"));
-    }
-
-    @Test
-    public void emptyLinesBetweenBlockTagsGetsFiltered() {
-        String comment = " * The type of the Object to be mapped." + EOL +
-                " * This interface maps the given Objects to existing ones in the database and" + EOL +
-                " * saves them." + EOL +
-                " * " + EOL +
-                " * @author censored" + EOL +
-                " * " + EOL +
-                " * @param <T>" + EOL;
-        Javadoc javadoc = JavaParser.parseJavadoc(comment);
-        assertEquals(2, javadoc.getBlockTags().size());
-    }
-
-    @Test
-    public void blockTagModificationWorks() {
-        Javadoc javadoc = new Javadoc(new JavadocDescription());
-
-        assertEquals(0, javadoc.getBlockTags().size());
-        JavadocBlockTag blockTag = new JavadocBlockTag(JavadocBlockTag.Type.RETURN, "a value");
-        javadoc.addBlockTag(blockTag);
-
-        assertEquals(1, javadoc.getBlockTags().size());
-        assertEquals(blockTag, javadoc.getBlockTags().get(0));
-
-        assertEquals(blockTag, javadoc.getBlockTags().remove(0));
-        assertEquals(0, javadoc.getBlockTags().size());
-    }
-
-    @Test
-    public void descriptionModificationWorks() {
-        JavadocDescription description = new JavadocDescription();
-
-        assertEquals(0, description.getElements().size());
-
-        JavadocDescriptionElement inlineTag = new JavadocInlineTag("inheritDoc", JavadocInlineTag.Type.INHERIT_DOC, "");
-        assertTrue(description.addElement(inlineTag));
-
-        assertEquals(1, description.getElements().size());
-        assertEquals(inlineTag, description.getElements().get(0));
-
-        assertEquals(inlineTag, description.getElements().remove(0));
-        assertEquals(0, description.getElements().size());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/javadoc/description/JavadocInlineTagTest.java b/javaparser-testing/src/test/java/com/github/javaparser/javadoc/description/JavadocInlineTagTest.java
deleted file mode 100644
index 128eb61..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/javadoc/description/JavadocInlineTagTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
- * Copyright (C) 2011, 2013-2017 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.javadoc.description;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class JavadocInlineTagTest {
-
-    @Test
-    public void javadocInlineTagShouldPersistCustomTagNames() {
-        String tag = JavadocInlineTag.fromText("{@foo something}").toText();
-
-        assertEquals(tag, "@foo something");
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/manual/BulkParseTest.java b/javaparser-testing/src/test/java/com/github/javaparser/manual/BulkParseTest.java
deleted file mode 100644
index b09651f..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/manual/BulkParseTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.github.javaparser.manual;
-
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.Problem;
-import com.github.javaparser.utils.CodeGenerationUtils;
-import com.github.javaparser.utils.Log;
-import com.github.javaparser.utils.SourceRoot;
-import com.github.javaparser.utils.SourceZip;
-import org.junit.Test;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_10;
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_9;
-import static com.github.javaparser.utils.CodeGenerationUtils.f;
-import static com.github.javaparser.utils.SourceRoot.Callback.Result.DONT_SAVE;
-import static com.github.javaparser.utils.TestUtils.download;
-import static com.github.javaparser.utils.TestUtils.temporaryDirectory;
-import static java.util.Comparator.comparing;
-
-public class BulkParseTest {
-    /**
-     * Running this will download a version of the OpenJDK, unzip it, and parse it. If it throws a stack overflow
-     * exception, increase the JVM's stack size.
-     */
-    public static void main(String[] args) throws IOException {
-        Log.setAdapter(new Log.StandardOutStandardErrorAdapter());
-        // This contains all kinds of test cases so it will lead to a lot of errors:
-        new BulkParseTest().parseOpenJdkLangToolsRepository();
-        // This contains the JDK source code, so it should have zero errors:
-        new BulkParseTest().parseJdkSrcZip();
-    }
-
-    private void parseOpenJdkLangToolsRepository() throws IOException {
-        Path workdir = CodeGenerationUtils.mavenModuleRoot(BulkParseTest.class).resolve(Paths.get(temporaryDirectory(), "javaparser_bulkparsetest"));
-        workdir.toFile().mkdirs();
-        Path openJdkZipPath = workdir.resolve("langtools.zip");
-        if (Files.notExists(openJdkZipPath)) {
-            Log.info("Downloading JDK langtools");
-            /* Found by choosing a tag here: http://hg.openjdk.java.net/jdk9/jdk9/langtools/tags
-             then copying the "zip" link to the line below: */ 
-            download(new URL("http://hg.openjdk.java.net/jdk10/jdk10/langtools/archive/19293ea3999f.zip"), openJdkZipPath);
-        }
-        bulkTest(new SourceZip(openJdkZipPath), "openjdk_src_repo_test_results.txt", new ParserConfiguration().setLanguageLevel(JAVA_10));
-    }
-
-    private void parseJdkSrcZip() throws IOException {
-        // This is where Ubuntu stores the contents of package openjdk-8-src
-        Path path = Paths.get("/usr/lib/jvm/openjdk-9/src.zip");
-        bulkTest(new SourceZip(path), "openjdk_src_zip_test_results.txt", new ParserConfiguration().setLanguageLevel(JAVA_9));
-    }
-
-    @Test
-    public void parseOwnSourceCode() throws IOException {
-        bulkTest(
-                new SourceRoot(CodeGenerationUtils.mavenModuleRoot(BulkParseTest.class).resolve("..")), 
-                "javaparser_test_results.txt", 
-                new ParserConfiguration().setLanguageLevel(JAVA_9));
-    }
-
-    public void bulkTest(SourceRoot sourceRoot, String testResultsFileName, ParserConfiguration configuration) throws IOException {
-        sourceRoot.setParserConfiguration(configuration);
-        TreeMap<Path, List<Problem>> results = new TreeMap<>(comparing(o -> o.toString().toLowerCase()));
-        sourceRoot.parseParallelized((localPath, absolutePath, result) -> {
-            if (!localPath.toString().contains("target")) {
-                if (!result.isSuccessful()) {
-                    results.put(localPath, result.getProblems());
-                }
-            }
-            return DONT_SAVE;
-        });
-        writeResults(results, testResultsFileName);
-    }
-
-    public void bulkTest(SourceZip sourceRoot, String testResultsFileName, ParserConfiguration configuration) throws IOException {
-        sourceRoot.setParserConfiguration(configuration);
-        TreeMap<Path, List<Problem>> results = new TreeMap<>(comparing(o -> o.toString().toLowerCase()));
-        sourceRoot.parse((path, result) -> {
-            if (!path.toString().contains("target")) {
-                if (!result.isSuccessful()) {
-                    results.put(path, result.getProblems());
-                }
-            }
-        });
-        writeResults(results, testResultsFileName);
-    }
-
-    private void writeResults(TreeMap<Path, List<Problem>> results, String testResultsFileName) throws IOException {
-        Log.info("Writing results...");
-
-        Path testResults = CodeGenerationUtils.mavenModuleRoot(BulkParseTest.class).resolve(Paths.get("..", "javaparser-testing", "src", "test", "resources", "com", "github", "javaparser", "bulk_test_results")).normalize();
-        testResults.toFile().mkdirs();
-        testResults = testResults.resolve(testResultsFileName);
-
-        int problemTotal = 0;
-        try (BufferedWriter writer = Files.newBufferedWriter(testResults)) {
-            for (Map.Entry<Path, List<Problem>> file : results.entrySet()) {
-                writer.write(file.getKey().toString().replace("\\", "/"));
-                writer.newLine();
-                for (Problem problem : file.getValue()) {
-                    writer.write(problem.getVerboseMessage());
-                    writer.newLine();
-                    problemTotal++;
-                }
-                writer.newLine();
-            }
-            writer.write(f("%s problems in %s files", problemTotal, results.size()));
-        }
-
-        Log.info("Results are in %s", testResults);
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/metamodel/BaseNodeMetaModelTest.java b/javaparser-testing/src/test/java/com/github/javaparser/metamodel/BaseNodeMetaModelTest.java
deleted file mode 100644
index 06a586c..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/metamodel/BaseNodeMetaModelTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import com.github.javaparser.ast.expr.StringLiteralExpr;
-import org.junit.Test;
-
-import java.util.Optional;
-
-import static org.junit.Assert.assertEquals;
-
-class TestMetaModel extends BaseNodeMetaModel {
-
-    public TestMetaModel() {
-        super(Optional.empty(), StringLiteralExpr.class, "stri", "com.japa", true, true);
-    }
-}
-
-public class BaseNodeMetaModelTest {
-    @Test
-    public void testGetters() {
-        TestMetaModel test = new TestMetaModel();
-
-        assertEquals("testMetaModel", test.getMetaModelFieldName());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/metamodel/PropertyMetaModelTest.java b/javaparser-testing/src/test/java/com/github/javaparser/metamodel/PropertyMetaModelTest.java
deleted file mode 100644
index 2333d81..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/metamodel/PropertyMetaModelTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.github.javaparser.metamodel;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.BodyDeclaration;
-import org.junit.Test;
-
-import java.util.Optional;
-
-import static org.junit.Assert.assertEquals;
-
-public class PropertyMetaModelTest {
-    @Test
-    public void whenPropertyIsVerySimpleThenTypeInfoIsCorrect() {
-        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", int.class, Optional.empty(), false, false, false, false, false);
-        assertEquals("int", bert.getTypeName());
-        assertEquals("int", bert.getTypeNameGenerified());
-        assertEquals("int", bert.getTypeNameForGetter());
-        assertEquals("int", bert.getTypeNameForSetter());
-    }
-
-    @Test
-    public void whenPropertyIsVeryComplexThenTypeInfoIsCorrect() {
-        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", BodyDeclaration.class, Optional.empty(), true, false, true, false, true);
-        assertEquals("BodyDeclaration", bert.getTypeName());
-        assertEquals("BodyDeclaration<?>", bert.getTypeNameGenerified());
-        assertEquals("Optional<NodeList<BodyDeclaration<?>>>", bert.getTypeNameForGetter());
-        assertEquals("NodeList<BodyDeclaration<?>>", bert.getTypeNameForSetter());
-    }
-
-    @Test
-    public void whenPropertyIsAnEnumThenTypeInfoIsCorrect() {
-        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", Modifier.class, Optional.empty(), false, false, false, true, false);
-        assertEquals("Modifier", bert.getTypeName());
-        assertEquals("Modifier", bert.getTypeNameGenerified());
-        assertEquals("EnumSet<Modifier>", bert.getTypeNameForGetter());
-        assertEquals("EnumSet<Modifier>", bert.getTypeNameForSetter());
-    }
-
-    @Test
-    public void metaModelFieldName() {
-        PropertyMetaModel bert = new PropertyMetaModel(null, "bert", Modifier.class, Optional.empty(), false, false, false, true, false);
-        assertEquals("bertPropertyMetaModel", bert.getMetaModelFieldName());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/modules/ModuleDeclarationTest.java b/javaparser-testing/src/test/java/com/github/javaparser/modules/ModuleDeclarationTest.java
deleted file mode 100644
index 80ebe55..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/modules/ModuleDeclarationTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package com.github.javaparser.modules;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.JavaToken;
-import com.github.javaparser.ParseStart;
-import com.github.javaparser.ParserConfiguration;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
-import com.github.javaparser.ast.modules.*;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import com.github.javaparser.printer.ConcreteSyntaxModel;
-import org.junit.Test;
-
-import static com.github.javaparser.GeneratedJavaParserConstants.IDENTIFIER;
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
-import static com.github.javaparser.JavaParser.parseName;
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_9;
-import static com.github.javaparser.Providers.provider;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-
-public class ModuleDeclarationTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
-
-    private final CompilationUnit parse(String code) {
-        return javaParser.parse(ParseStart.COMPILATION_UNIT, provider(code)).getResult().get();
-    }
-
-    @Test
-    public void moduleInfoKeywordsAreSeenAsIdentifiers() {
-        CompilationUnit cu = parse("class module { }");
-        JavaToken moduleToken = cu.getClassByName("module").get().getName().getTokenRange().get().getBegin();
-        assertEquals(IDENTIFIER, moduleToken.getKind());
-    }
-
-    @Test
-    public void issue988RequireTransitiveShouldRequireAModuleCalledTransitive() {
-        CompilationUnit cu = parse("module X { requires transitive; }");
-        ModuleRequiresStmt requiresTransitive = (ModuleRequiresStmt) cu.getModule().get().getModuleStmts().get(0);
-        assertEquals("transitive", requiresTransitive.getNameAsString());
-        assertEquals(IDENTIFIER, requiresTransitive.getName().getTokenRange().get().getBegin().getKind());
-    }
-
-    @Test
-    public void jlsExample1() {
-        CompilationUnit cu = parse(
-                "@Foo(1) @Foo(2) @Bar " +
-                        "module M.N {" +
-                        "  requires A.B;" +
-                        "  requires transitive C.D;" +
-                        "  requires static E.F;" +
-                        "  requires transitive static G.H;" +
-                        "" +
-                        "  exports P.Q;" +
-                        "  exports R.S to T1.U1, T2.U2;" +
-                        "" +
-                        "  opens P.Q;" +
-                        "  opens R.S to T1.U1, T2.U2;" +
-                        "" +
-                        "  uses V.W;" +
-                        "  provides X.Y with Z1.Z2, Z3.Z4;" +
-                        "}");
-
-        ModuleDeclaration module = cu.getModule().get();
-        assertEquals("M.N", module.getNameAsString());
-        assertEquals(false, module.isOpen());
-        assertThat(module.getAnnotations()).containsExactly(
-                new SingleMemberAnnotationExpr(new Name("Foo"), new IntegerLiteralExpr("1")),
-                new SingleMemberAnnotationExpr(new Name("Foo"), new IntegerLiteralExpr("2")),
-                new MarkerAnnotationExpr(new Name("Bar")));
-
-        ModuleRequiresStmt moduleRequiresStmt = module.getModuleStmts().get(0).asModuleRequiresStmt();
-        assertThat(moduleRequiresStmt.getNameAsString()).isEqualTo("A.B");
-        assertThat(moduleRequiresStmt.getModifiers()).isEmpty();
-
-        ModuleExportsStmt moduleExportsStmt = module.getModuleStmts().get(5).asModuleExportsStmt();
-        assertThat(moduleExportsStmt.getNameAsString()).isEqualTo("R.S");
-        assertThat(moduleExportsStmt.getModuleNames()).containsExactly(parseName("T1.U1"), parseName("T2.U2"));
-
-        ModuleOpensStmt moduleOpensStmt = module.getModuleStmts().get(7).asModuleOpensStmt();
-        assertThat(moduleOpensStmt.getNameAsString()).isEqualTo("R.S");
-        assertThat(moduleOpensStmt.getModuleNames()).containsExactly(parseName("T1.U1"), parseName("T2.U2"));
-
-        ModuleUsesStmt moduleUsesStmt = module.getModuleStmts().get(8).asModuleUsesStmt();
-        assertThat(moduleUsesStmt.getType().toString()).isEqualTo("V.W");
-
-        ModuleProvidesStmt moduleProvidesStmt = module.getModuleStmts().get(9).asModuleProvidesStmt();
-        assertThat(moduleProvidesStmt.getType().toString()).isEqualTo("X.Y");
-        assertThat(moduleProvidesStmt.getWithTypes()).containsExactly(
-                new ClassOrInterfaceType(parseClassOrInterfaceType("Z1"), "Z2"),
-                new ClassOrInterfaceType(parseClassOrInterfaceType("Z3"), "Z4"));
-
-    }
-
-    @Test
-    public void jlsExample2HasAnOpenModule() {
-        CompilationUnit cu = parse("open module M.N {}");
-
-        ModuleDeclaration module = cu.getModule().get();
-        assertEquals("M.N", module.getNameAsString());
-        assertEquals(true, module.isOpen());
-    }
-
-    @Test
-    public void testPrettyPrinting() {
-        CompilationUnit cu = parse(
-                "@Foo(1) @Foo(2) @Bar " +
-                        "module M.N {" +
-                        "  requires A.B;" +
-                        "  requires transitive C.D;" +
-                        "  requires static E.F;" +
-                        "  requires transitive static G.H;" +
-                        "" +
-                        "  exports P.Q;" +
-                        "  exports R.S to T1.U1, T2.U2;" +
-                        "" +
-                        "  opens P.Q;" +
-                        "  opens R.S to T1.U1, T2.U2;" +
-                        "" +
-                        "  uses V.W;" +
-                        "  provides X.Y with Z1.Z2, Z3.Z4;" +
-                        "}");
-
-        assertEquals(
-                "@Foo(1) @Foo(2) @Bar " + EOL +
-                        "module M.N {" + EOL +
-                        "    requires A.B;" + EOL +
-                        "    requires transitive C.D;" + EOL +
-                        "    requires static E.F;" + EOL +
-                        "    requires static transitive G.H;" + EOL +
-                        "    exports P.Q;" + EOL +
-                        "    exports R.S to T1.U1, T2.U2;" + EOL +
-                        "    opens P.Q;" + EOL +
-                        "    opens R.S to T1.U1, T2.U2;" + EOL +
-                        "    uses V.W;" + EOL +
-                        "    provides X.Y with Z1.Z2, Z3.Z4;" + EOL +
-                        "}" + EOL, cu.toString());
-
-    }
-
-    @Test
-    public void testCsmPrinting() {
-        CompilationUnit cu = parse(
-                "@Foo(1) @Foo(2) @Bar " +
-                        "open module M.N {" +
-                        "  requires A.B;" +
-                        "  requires transitive C.D;" +
-                        "  requires static E.F;" +
-                        "  requires transitive static G.H;" +
-                        "" +
-                        "  exports P.Q;" +
-                        "  exports R.S to T1.U1, T2.U2;" +
-                        "" +
-                        "  opens P.Q;" +
-                        "  opens R.S to T1.U1, T2.U2;" +
-                        "" +
-                        "  uses V.W;" +
-                        "  provides X.Y with Z1.Z2, Z3.Z4;" +
-                        "}");
-
-        assertEquals(
-                "@Foo(1) @Foo(2) @Bar" + EOL +
-                        "open module M.N {" + EOL +
-                        "    requires A.B;" + EOL +
-                        "    requires transitive C.D;" + EOL +
-                        "    requires static E.F;" + EOL +
-                        "    requires static transitive G.H;" + EOL +
-                        "    exports P.Q;" + EOL +
-                        "    exports R.S to T1.U1, T2.U2;" + EOL +
-                        "    opens P.Q;" + EOL +
-                        "    opens R.S to T1.U1, T2.U2;" + EOL +
-                        "    uses V.W;" + EOL +
-                        "    provides X.Y with Z1.Z2, Z3.Z4;" + EOL +
-                        "}" + EOL, ConcreteSyntaxModel.genericPrettyPrint(cu));
-
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelAcceptanceTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelAcceptanceTest.java
deleted file mode 100644
index af47a9d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelAcceptanceTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.printer;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.utils.CodeGenerationUtils;
-import com.github.javaparser.utils.TestUtils;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.file.Path;
-
-import static org.junit.Assert.assertEquals;
-
-public class ConcreteSyntaxModelAcceptanceTest {
-    private final Path rootDir = CodeGenerationUtils.mavenModuleRoot(ConcreteSyntaxModelAcceptanceTest.class).resolve("src/test/test_sourcecode");
-
-    private String prettyPrint(Node node) {
-        return ConcreteSyntaxModel.genericPrettyPrint(node);
-    }
-
-    private String prettyPrintedExpectation(String name) throws IOException {
-        return TestUtils.readResource("com/github/javaparser/printer/" + name + "_prettyprinted");
-    }
-
-    @Test
-    public void printingExamplePrettyPrintVisitor() throws IOException {
-        CompilationUnit cu = JavaParser.parse(rootDir.resolve("com/github/javaparser/printer/PrettyPrintVisitor.java"));
-        assertEquals(prettyPrintedExpectation("PrettyPrintVisitor"), prettyPrint(cu));
-    }
-
-    @Test
-    public void printingExampleJavaConcepts() throws IOException {
-        CompilationUnit cu = JavaParser.parse(rootDir.resolve("com/github/javaparser/printer/JavaConcepts.java"));
-        assertEquals(prettyPrintedExpectation("JavaConcepts"), prettyPrint(cu));
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelTest.java
deleted file mode 100644
index b08f90b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/ConcreteSyntaxModelTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.printer;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.expr.ClassExpr;
-import org.junit.Test;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class ConcreteSyntaxModelTest {
-
-    private String print(Node node) {
-        return ConcreteSyntaxModel.genericPrettyPrint(node);
-    }
-
-    @Test
-    public void printSimpleClassExpr() {
-        ClassExpr expr = JavaParser.parseExpression("Foo.class");
-        assertEquals("Foo.class", print(expr));
-    }
-
-    @Test
-    public void printArrayClassExpr() {
-        ClassExpr expr = JavaParser.parseExpression("Foo[].class");
-        assertEquals("Foo[].class", print(expr));
-    }
-
-    @Test
-    public void printGenericClassExpr() {
-        ClassExpr expr = JavaParser.parseExpression("Foo<String>.class");
-        assertEquals("Foo<String>.class", print(expr));
-    }
-
-    @Test
-    public void printSimplestClass() {
-        Node node = JavaParser.parse("class A {}");
-        assertEquals("class A {" + EOL +
-                "}" + EOL, print(node));
-    }
-
-    @Test
-    public void printAClassWithField() {
-        Node node = JavaParser.parse("class A { int a; }");
-        assertEquals("class A {" + EOL
-                + EOL +
-                "    int a;" + EOL +
-                "}" + EOL, print(node));
-    }
-
-    @Test
-    public void printParameters() {
-        Node node = JavaParser.parseBodyDeclaration("int x(int y, int z) {}");
-        assertEquals("int x(int y, int z) {" + EOL + "}", print(node));
-    }
-
-    @Test
-    public void printReceiverParameter() {
-        Node node = JavaParser.parseBodyDeclaration("int x(X A.B.this, int y, int z) {}");
-        assertEquals("int x(X A.B.this, int y, int z) {" + EOL + "}", print(node));
-    }
-
-    @Test
-    public void printAnEmptyInterface() {
-        Node node = JavaParser.parse("interface A {}");
-        assertEquals("interface A {" + EOL +
-                "}" + EOL, print(node));
-    }
-
-    @Test
-    public void printAnEmptyInterfaceWithModifier() {
-        Node node = JavaParser.parse("public interface A {}");
-        assertEquals("public interface A {" + EOL +
-                "}" + EOL, print(node));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/DotPrinterTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/DotPrinterTest.java
deleted file mode 100644
index ca11465..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/DotPrinterTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*

- * 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.printer;

-

-import static org.junit.Assert.assertEquals;

-

-import org.junit.Test;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ast.expr.Expression;

-

-public class DotPrinterTest {

-    @Test

-    public void testWithType() {

-        String expectedOutput = "digraph {" + System.lineSeparator();

-        expectedOutput += "n0 [label=\"root (MethodCallExpr)\"];" + System.lineSeparator();

-        expectedOutput += "n1 [label=\"name (SimpleName)\"];" + System.lineSeparator();

-        expectedOutput += "n0 -> n1;" + System.lineSeparator();

-        expectedOutput += "n2 [label=\"identifier='x'\"];" + System.lineSeparator();

-        expectedOutput += "n1 -> n2;" + System.lineSeparator();

-        expectedOutput += "n3 [label=\"arguments\"];" + System.lineSeparator();

-        expectedOutput += "n0 -> n3;" + System.lineSeparator();

-        expectedOutput += "n4 [label=\"argument (IntegerLiteralExpr)\"];" + System.lineSeparator();

-        expectedOutput += "n3 -> n4;" + System.lineSeparator();

-        expectedOutput += "n5 [label=\"value='1'\"];" + System.lineSeparator();

-        expectedOutput += "n4 -> n5;" + System.lineSeparator();

-        expectedOutput += "n6 [label=\"argument (IntegerLiteralExpr)\"];" + System.lineSeparator();

-        expectedOutput += "n3 -> n6;" + System.lineSeparator();

-        expectedOutput += "n7 [label=\"value='1'\"];" + System.lineSeparator();

-        expectedOutput += "n6 -> n7;" + System.lineSeparator();

-        expectedOutput += "}";

-

-        DotPrinter dotPrinter = new DotPrinter(true);

-        Expression expression = JavaParser.parseExpression("x(1,1)");

-        String output = dotPrinter.output(expression);

-        assertEquals(expectedOutput, output);

-    }

-

-    @Test

-    public void testWithoutType() {

-        String expectedOutput = "digraph {" + System.lineSeparator();

-        expectedOutput += "n0 [label=\"root\"];" + System.lineSeparator();

-        expectedOutput += "n1 [label=\"operator='PLUS'\"];" + System.lineSeparator();

-        expectedOutput += "n0 -> n1;" + System.lineSeparator();

-        expectedOutput += "n2 [label=\"left\"];" + System.lineSeparator();

-        expectedOutput += "n0 -> n2;" + System.lineSeparator();

-        expectedOutput += "n3 [label=\"value='1'\"];" + System.lineSeparator();

-        expectedOutput += "n2 -> n3;" + System.lineSeparator();

-        expectedOutput += "n4 [label=\"right\"];" + System.lineSeparator();

-        expectedOutput += "n0 -> n4;" + System.lineSeparator();

-        expectedOutput += "n5 [label=\"value='1'\"];" + System.lineSeparator();

-        expectedOutput += "n4 -> n5;" + System.lineSeparator();

-        expectedOutput += "}";

-

-        DotPrinter dotPrinter = new DotPrinter(false);

-        Expression expression = JavaParser.parseExpression("1+1");

-        String output = dotPrinter.output(expression);

-        assertEquals(expectedOutput, output);

-    }

-}

diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/JsonPrinterTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/JsonPrinterTest.java
deleted file mode 100644
index 7e26254..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/JsonPrinterTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.github.javaparser.printer;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.expr.Expression;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.*;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.*;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.io.BufferedWriter;
-
-public class JsonPrinterTest {
-    @Test
-    public void testWithType() {
-        JsonPrinter jsonPrinter = new JsonPrinter(true);
-        Expression expression = parseExpression("x(1,1)");
-
-        String output = jsonPrinter.output(expression);
-
-        assertEquals("{\"type\":\"MethodCallExpr\",\"name\":{\"type\":\"SimpleName\",\"identifier\":\"x\"},\"arguments\":[{\"type\":\"IntegerLiteralExpr\",\"value\":\"1\"},{\"type\":\"IntegerLiteralExpr\",\"value\":\"1\"}]}", output);
-    }
-
-    @Test
-    public void testWithoutType() {
-        JsonPrinter jsonPrinter = new JsonPrinter(false);
-        Expression expression = parseExpression("1+1");
-
-        String output = jsonPrinter.output(expression);
-
-        assertEquals("{\"operator\":\"PLUS\",\"left\":{\"value\":\"1\"},\"right\":{\"value\":\"1\"}}", output);
-    }
-
-    @Test
-    public void testEscaping() {
-        JsonPrinter jsonPrinter = new JsonPrinter(false);
-        CompilationUnit expression = parse("class X {//hi\"" + EOL + "int x;}");
-
-        String output = jsonPrinter.output(expression);
-
-        assertEquals("{\"types\":[{\"isInterface\":\"false\",\"name\":{\"identifier\":\"X\",\"comment\":{\"content\":\"hi\\\"\"}},\"members\":[{\"variables\":[{\"name\":{\"identifier\":\"x\"},\"type\":{\"type\":\"INT\"}}]}]}]}", output);
-    }
-
-    @Test
-    public void issue1338() {
-        String code = "class Test {" +
-                "  public void method() {" +
-                "    String.format(\"I'm using %s\", \"JavaParser\");" +
-                "  }" +
-                "}";
-        CompilationUnit unit = parse(code);
-        JsonPrinter printer = new JsonPrinter(true);
-        printer.output(unit);
-    }
-
-    @Test
-    public void issue1421() {
-        // Handle multi-line strings in JSON output
-        String code = "/* \n" +
-                "* Some comment\n" +
-                "*/\n" +
-                "public class Test {}";
-        CompilationUnit unit = parse(code);
-        JsonPrinter printer = new JsonPrinter(true);
-
-        String output = printer.output(unit);
-
-        assertEquals("{\"type\":\"CompilationUnit\",\"types\":[{\"type\":\"ClassOrInterfaceDeclaration\",\"isInterface\":\"false\",\"name\":{\"type\":\"SimpleName\",\"identifier\":\"Test\"},\"comment\":{\"type\":\"BlockComment\",\"content\":\" \\n* Some comment\\n\"}}]}", output);
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java
deleted file mode 100644
index df1168e..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/PrettyPrintVisitorTest.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * 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.printer;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.comments.LineComment;
-import com.github.javaparser.ast.expr.CastExpr;
-import com.github.javaparser.ast.expr.ClassExpr;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.type.Type;
-import org.junit.Test;
-
-import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-
-public class PrettyPrintVisitorTest {
-
-    @Test
-    public void getMaximumCommonTypeWithoutAnnotations() {
-        VariableDeclarationExpr vde1 = JavaParser.parseVariableDeclarationExpr("int a[], b[]");
-        assertEquals("int[]", vde1.getMaximumCommonType().get().toString());
-
-        VariableDeclarationExpr vde2 = JavaParser.parseVariableDeclarationExpr("int[][] a[], b[]");
-        assertEquals("int[][][]", vde2.getMaximumCommonType().get().toString());
-
-        VariableDeclarationExpr vde3 = JavaParser.parseVariableDeclarationExpr("int[][] a, b[]");
-        assertEquals("int[][]", vde3.getMaximumCommonType().get().toString());
-    }
-
-    @Test
-    public void getMaximumCommonTypeWithAnnotations() {
-        VariableDeclarationExpr vde1 = JavaParser.parseVariableDeclarationExpr("int a @Foo [], b[]");
-        assertEquals("int", vde1.getMaximumCommonType().get().toString());
-
-        VariableDeclarationExpr vde2 = JavaParser.parseVariableDeclarationExpr("int[]@Foo [] a[], b[]");
-        assertEquals("int[] @Foo [][]", vde2.getMaximumCommonType().get().toString());
-    }
-
-    private String print(Node node) {
-        return new PrettyPrinter().print(node);
-    }
-
-    @Test
-    public void printSimpleClassExpr() {
-        ClassExpr expr = JavaParser.parseExpression("Foo.class");
-        assertEquals("Foo.class", print(expr));
-    }
-
-    @Test
-    public void printArrayClassExpr() {
-        ClassExpr expr = JavaParser.parseExpression("Foo[].class");
-        assertEquals("Foo[].class", print(expr));
-    }
-
-    @Test
-    public void printGenericClassExpr() {
-        ClassExpr expr = JavaParser.parseExpression("Foo<String>.class");
-        assertEquals("Foo<String>.class", print(expr));
-    }
-
-    @Test
-    public void printSimplestClass() {
-        Node node = JavaParser.parse("class A {}");
-        assertEquals("class A {" + EOL +
-                "}" + EOL, print(node));
-    }
-
-    @Test
-    public void printAClassWithField() {
-        Node node = JavaParser.parse("class A { int a; }");
-        assertEquals("class A {" + EOL
-                + EOL +
-                "    int a;" + EOL +
-                "}" + EOL, print(node));
-    }
-
-    @Test
-    public void printAReceiverParameter() {
-        Node node = JavaParser.parseBodyDeclaration("int x(@O X A.B.this, int y) { }");
-        assertEquals("int x(@O X A.B.this, int y) {" + EOL + "}", print(node));
-    }
-
-    @Test
-    public void printLambdaIntersectionTypeAssignment() {
-        String code = "class A {" + EOL +
-                "  void f() {" + EOL +
-                "    Runnable r = (Runnable & Serializable) (() -> {});" + EOL +
-                "    r = (Runnable & Serializable)() -> {};" + EOL +
-                "    r = (Runnable & I)() -> {};" + EOL +
-                "  }}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodDeclaration methodDeclaration = (MethodDeclaration) cu.getType(0).getMember(0);
-
-        assertEquals("Runnable r = (Runnable & Serializable) (() -> {" + EOL + "});", print(methodDeclaration.getBody().get().getStatements().get(0)));
-    }
-
-    @Test
-    public void printIntersectionType() {
-        String code = "(Runnable & Serializable) (() -> {})";
-        Expression expression = JavaParser.parseExpression(code);
-        Type type = ((CastExpr) expression).getType();
-
-        assertEquals("Runnable & Serializable", print(type));
-    }
-
-    @Test
-    public void printLambdaIntersectionTypeReturn() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        CompilationUnit cu = JavaParser.parse(code);
-        MethodDeclaration methodDeclaration = (MethodDeclaration) cu.getType(0).getMember(0);
-
-        assertEquals("return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getKey().compareTo(c2.getKey());", print(methodDeclaration.getBody().get().getStatements().get(0)));
-    }
-
-    @Test
-    public void printClassWithoutJavaDocButWithComment() {
-        String code = String.format("/** javadoc */ public class A { %s// stuff%s}", EOL, EOL);
-        CompilationUnit cu = JavaParser.parse(code);
-        PrettyPrinterConfiguration ignoreJavaDoc = new PrettyPrinterConfiguration().setPrintJavadoc(false);
-        String content = cu.toString(ignoreJavaDoc);
-        assertEquals(String.format("public class A {%s    // stuff%s}%s", EOL, EOL, EOL), content);
-    }
-
-    @Test
-    public void printImportsDefaultOrder() {
-        String code = "import x.y.z;import a.b.c;import static b.c.d;class c {}";
-        CompilationUnit cu = JavaParser.parse(code);
-        String content = cu.toString();
-        assertEqualsNoEol("import x.y.z;\n" +
-                "import a.b.c;\n" +
-                "import static b.c.d;\n" +
-                "\n" +
-                "class c {\n" +
-                "}\n", content);
-    }
-
-    @Test
-    public void printImportsOrdered() {
-        String code = "import x.y.z;import a.b.c;import static b.c.d;class c {}";
-        CompilationUnit cu = JavaParser.parse(code);
-        PrettyPrinterConfiguration orderImports = new PrettyPrinterConfiguration().setOrderImports(true);
-        String content = cu.toString(orderImports);
-        assertEqualsNoEol("import static b.c.d;\n" +
-                "import a.b.c;\n" +
-                "import x.y.z;\n" +
-                "\n" +
-                "class c {\n" +
-                "}\n", content);
-    }
-
-    @Test
-    public void multilineJavadocGetsFormatted() {
-        CompilationUnit cu = new CompilationUnit();
-        cu.addClass("X").addMethod("abc").setJavadocComment("line1\n   line2 *\n * line3");
-
-        assertEqualsNoEol("public class X {\n" +
-                "\n" +
-                "    /**\n" +
-                "     * line1\n" +
-                "     *   line2 *\n" +
-                "     * line3\n" +
-                "     */\n" +
-                "    void abc() {\n" +
-                "    }\n" +
-                "}\n", cu.toString());
-    }
-
-    @Test
-    public void emptyJavadocGetsFormatted() {
-        CompilationUnit cu = new CompilationUnit();
-        cu.addClass("X").addMethod("abc").setJavadocComment("");
-
-        assertEqualsNoEol("public class X {\n" +
-                "\n" +
-                "    /**\n" +
-                "     */\n" +
-                "    void abc() {\n" +
-                "    }\n" +
-                "}\n", cu.toString());
-    }
-
-    @Test
-    public void multilineJavadocWithLotsOfEmptyLinesGetsFormattedNeatly() {
-        CompilationUnit cu = new CompilationUnit();
-        cu.addClass("X").addMethod("abc").setJavadocComment("\n\n\n ab\n\n\n cd\n\n\n");
-
-        assertEqualsNoEol("public class X {\n" +
-                "\n" +
-                "    /**\n" +
-                "     * ab\n" +
-                "     *\n" +
-                "     * cd\n" +
-                "     */\n" +
-                "    void abc() {\n" +
-                "    }\n" +
-                "}\n", cu.toString());
-    }
-
-    @Test
-    public void singlelineJavadocGetsFormatted() {
-        CompilationUnit cu = new CompilationUnit();
-        cu.addClass("X").addMethod("abc").setJavadocComment("line1");
-
-        assertEqualsNoEol("public class X {\n" +
-                "\n" +
-                "    /**\n" +
-                "     * line1\n" +
-                "     */\n" +
-                "    void abc() {\n" +
-                "    }\n" +
-                "}\n", cu.toString());
-    }
-
-    @Test
-    public void singlelineCommentGetsFormatted() {
-        CompilationUnit cu = new CompilationUnit();
-        cu.addClass("X").addMethod("abc").setComment(new LineComment("   line1  \n "));
-
-        assertEqualsNoEol("public class X {\n" +
-                "\n" +
-                "    // line1\n" +
-                "    void abc() {\n" +
-                "    }\n" +
-                "}\n", cu.toString());
-    }
-
-    @Test
-    public void blockcommentGetsNoFormatting() {
-        CompilationUnit cu = JavaParser.parse("class A {\n" +
-                "    public void helloWorld(String greeting, String name) {\n" +
-                "        //sdfsdfsdf\n" +
-                "            //sdfds\n" +
-                "        /*\n" +
-                "                            dgfdgfdgfdgfdgfd\n" +
-                "         */\n" +
-                "    }\n" +
-                "}\n");
-
-        assertEqualsNoEol("class A {\n" +
-                "\n" +
-                "    public void helloWorld(String greeting, String name) {\n" +
-                "    // sdfsdfsdf\n" +
-                "    // sdfds\n" +
-                "    /*\n" +
-                "                            dgfdgfdgfdgfdgfd\n" +
-                "         */\n" +
-                "    }\n" +
-                "}\n", cu.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/PrettyPrinterTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/PrettyPrinterTest.java
deleted file mode 100644
index fef3609..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/PrettyPrinterTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.printer;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
-import com.github.javaparser.ast.type.PrimitiveType;
-import org.junit.Test;
-
-import static com.github.javaparser.JavaParser.*;
-import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
-import static org.junit.Assert.assertEquals;
-
-public class PrettyPrinterTest {
-
-    private String prettyPrintField(String code) {
-        CompilationUnit cu = parse(code);
-        return new PrettyPrinter().print(cu.findFirst(FieldDeclaration.class).get());
-    }
-
-    private String prettyPrintVar(String code) {
-        CompilationUnit cu = parse(code);
-        return new PrettyPrinter().print(cu.findAll(VariableDeclarationExpr.class).get(0));
-    }
-
-    @Test
-    public void printingArrayFields() {
-        String code;
-        code = "class A { int a, b[]; }";
-        assertEquals("int a, b[];", prettyPrintField(code));
-
-        code = "class A { int[] a[], b[]; }";
-        assertEquals("int[][] a, b;", prettyPrintField(code));
-
-        code = "class A { int[] a[][], b; }";
-        assertEquals("int[] a[][], b;", prettyPrintField(code));
-
-        code = "class A { int[] a, b; }";
-        assertEquals("int[] a, b;", prettyPrintField(code));
-
-        code = "class A { int a[], b[]; }";
-        assertEquals("int[] a, b;", prettyPrintField(code));
-    }
-
-    @Test
-    public void printingArrayVariables() {
-        String code;
-        code = "class A { void foo(){ int a, b[]; }}";
-        assertEquals("int a, b[]", prettyPrintVar(code));
-
-        code = "class A { void foo(){ int[] a[], b[]; }}";
-        assertEquals("int[][] a, b", prettyPrintVar(code));
-
-        code = "class A { void foo(){ int[] a[][], b; }}";
-        assertEquals("int[] a[][], b", prettyPrintVar(code));
-
-        code = "class A { void foo(){ int[] a, b; }}";
-        assertEquals("int[] a, b", prettyPrintVar(code));
-
-        code = "class A { void foo(){ int a[], b[]; }}";
-        assertEquals("int[] a, b", prettyPrintVar(code));
-    }
-
-    private String prettyPrintConfigurable(String code) {
-        CompilationUnit cu = parse(code);
-        PrettyPrinter printer = new PrettyPrinter(new PrettyPrinterConfiguration().setVisitorFactory(TestVisitor::new));
-        return printer.print(cu.findFirst(ClassOrInterfaceDeclaration.class).get());
-    }
-
-    @Test
-    public void printUseTestVisitor() {
-        String code;
-        code = "class A { void foo(){ int a, b[]; }}";
-        assertEquals("test", prettyPrintConfigurable(code));
-    }
-
-    @Test
-    public void prettyColumnAlignParameters_enabled() {
-        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration()
-                .setIndent("\t")
-                .setColumnAlignParameters(true);
-
-        final String EOL = config.getEndOfLineCharacter();
-
-        String code = "class Example { void foo(Object arg0,Object arg1){ myMethod(1, 2, 3, 5, Object.class); } }";
-        String expected = "class Example {" + EOL +
-                "" + EOL +
-                "\tvoid foo(Object arg0, Object arg1) {" + EOL +
-                "\t\tmyMethod(1," + EOL +
-                "\t\t         2," + EOL +
-                "\t\t         3," + EOL +
-                "\t\t         5," + EOL +
-                "\t\t         Object.class);" + EOL +
-                "\t}" + EOL +
-                "}" + EOL +
-                "";
-
-        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
-    }
-
-    @Test
-    public void prettyColumnAlignParameters_disabled() {
-        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration();
-        final String EOL = config.getEndOfLineCharacter();
-
-        String code = "class Example { void foo(Object arg0,Object arg1){ myMethod(1, 2, 3, 5, Object.class); } }";
-        String expected = "class Example {" + EOL +
-                "" + EOL +
-                "    void foo(Object arg0, Object arg1) {" + EOL +
-                "        myMethod(1, 2, 3, 5, Object.class);" + EOL +
-                "    }" + EOL +
-                "}" + EOL +
-                "";
-
-        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
-    }
-
-    @Test
-    public void prettyAlignMethodCallChains_enabled() {
-        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration()
-                .setIndent("\t")
-                .setColumnAlignFirstMethodChain(true);
-
-        final String EOL = config.getEndOfLineCharacter();
-
-        String code = "class Example { void foo() { IntStream.range(0, 10).filter(x -> x % 2 == 0).map(x -> x * IntStream.of(1,3,5,1).sum()).forEach(System.out::println); } }";
-        String expected = "class Example {" + EOL +
-                "" + EOL +
-                "\tvoid foo() {" + EOL +
-                "\t\tIntStream.range(0, 10)" + EOL +
-                "\t\t         .filter(x -> x % 2 == 0)" + EOL +
-                "\t\t         .map(x -> x * IntStream.of(1, 3, 5, 1)" + EOL +
-                "\t\t                                .sum())" + EOL +
-                "\t\t         .forEach(System.out::println);" + EOL +
-                "\t}" + EOL +
-                "}" + EOL +
-                "";
-
-        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
-    }
-
-    @Test
-    public void prettyAlignMethodCallChains_disabled() {
-        PrettyPrinterConfiguration config = new PrettyPrinterConfiguration();
-        final String EOL = config.getEndOfLineCharacter();
-
-        String code = "class Example { void foo() { IntStream.range(0, 10).filter(x -> x % 2 == 0).map(x -> x * IntStream.of(1,3,5,1).sum()).forEach(System.out::println); } }";
-        String expected = "class Example {" + EOL +
-                "" + EOL +
-                "    void foo() {" + EOL +
-                "        IntStream.range(0, 10).filter(x -> x % 2 == 0).map(x -> x * IntStream.of(1, 3, 5, 1).sum()).forEach(System.out::println);" + EOL +
-                "    }" + EOL +
-                "}" + EOL +
-                "";
-
-        assertEquals(expected, new PrettyPrinter(config).print(parse(code)));
-    }
-
-    @Test
-    public void enumConstantsHorizontally() {
-        CompilationUnit cu = parse("enum X{A, B, C, D, E}");
-        assertEqualsNoEol("enum X {\n\n    A, B, C, D, E\n}\n", new PrettyPrinter().print(cu));
-    }
-
-    @Test
-    public void enumConstantsVertically() {
-        CompilationUnit cu = parse("enum X{A, B, C, D, E, F}");
-        assertEqualsNoEol("enum X {\n\n    A,\n    B,\n    C,\n    D,\n    E,\n    F\n}\n", new PrettyPrinter().print(cu));
-    }
-
-    @Test
-    public void printingInconsistentVariables() {
-        FieldDeclaration fieldDeclaration = parseBodyDeclaration("int a, b;").asFieldDeclaration();
-
-        assertEquals("int a, b;", fieldDeclaration.toString());
-
-        fieldDeclaration.getVariable(0).setType(PrimitiveType.doubleType());
-
-        assertEquals("??? a, b;", fieldDeclaration.toString());
-
-        fieldDeclaration.getVariable(1).setType(PrimitiveType.doubleType());
-
-        assertEquals("double a, b;", fieldDeclaration.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/XmlPrinterTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/XmlPrinterTest.java
deleted file mode 100644
index b649891..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/XmlPrinterTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.github.javaparser.printer;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.expr.Expression;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class XmlPrinterTest {
-    @Test
-    public void testWithType() {
-        Expression expression = JavaParser.parseExpression("1+1");
-        XmlPrinter xmlOutput = new XmlPrinter(true);
-
-        String output = xmlOutput.output(expression);
-
-        assertEquals("<root type='BinaryExpr' operator='PLUS'><left type='IntegerLiteralExpr' value='1'></left><right type='IntegerLiteralExpr' value='1'></right></root>", output);
-    }
-
-    @Test
-    public void testWithoutType() {
-        Expression expression = JavaParser.parseExpression("1+1");
-
-        XmlPrinter xmlOutput = new XmlPrinter(false);
-
-        String output = xmlOutput.output(expression);
-
-        assertEquals("<root operator='PLUS'><left value='1'></left><right value='1'></right></root>", output);
-    }
-
-    @Test
-    public void testList() {
-        Expression expression = JavaParser.parseExpression("a(1,2)");
-
-        XmlPrinter xmlOutput = new XmlPrinter(true);
-
-        String output = xmlOutput.output(expression);
-
-        assertEquals("<root type='MethodCallExpr'><name type='SimpleName' identifier='a'></name><arguments><argument type='IntegerLiteralExpr' value='1'></argument><argument type='IntegerLiteralExpr' value='2'></argument></arguments></root>", output);
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/YamlPrinterTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/YamlPrinterTest.java
deleted file mode 100644
index 435cd81..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/YamlPrinterTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*

- * 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.printer;

-

-import static org.junit.Assert.assertEquals;

-

-import org.junit.Test;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ast.expr.Expression;

-

-public class YamlPrinterTest {

-

-    @Test

-    public void testWithType() {

-        String expectedOutput = "---" + System.lineSeparator();

-        expectedOutput += "root(Type=MethodCallExpr): " + System.lineSeparator();

-        expectedOutput += "    name(Type=SimpleName): " + System.lineSeparator();

-        expectedOutput += "        identifier: \"x\"" + System.lineSeparator();

-        expectedOutput += "    arguments: " + System.lineSeparator();

-        expectedOutput += "        - argument(Type=IntegerLiteralExpr): " + System.lineSeparator();

-        expectedOutput += "            value: \"1\"" + System.lineSeparator();

-        expectedOutput += "        - argument(Type=IntegerLiteralExpr): " + System.lineSeparator();

-        expectedOutput += "            value: \"1\"" + System.lineSeparator();

-        expectedOutput += "...";

-

-        YamlPrinter yamlPrinter = new YamlPrinter(true);

-        Expression expression = JavaParser.parseExpression("x(1,1)");

-        String output = yamlPrinter.output(expression);

-        assertEquals(expectedOutput, output);

-    }

-

-    @Test

-    public void testWithoutType() {

-        String expectedOutput = "---" + System.lineSeparator();

-        expectedOutput += "root: " + System.lineSeparator();

-        expectedOutput += "    operator: \"PLUS\"" + System.lineSeparator();

-        expectedOutput += "    left: " + System.lineSeparator();

-        expectedOutput += "        value: \"1\"" + System.lineSeparator();

-        expectedOutput += "    right: " + System.lineSeparator();

-        expectedOutput += "        value: \"1\"" + System.lineSeparator();

-        expectedOutput += "...";

-

-        YamlPrinter yamlPrinter = new YamlPrinter(false);

-        Expression expression = JavaParser.parseExpression("1+1");

-        String output = yamlPrinter.output(expression);

-        assertEquals(expectedOutput, output);

-    }

-

-    @Test

-    public void testWithColonFollowedBySpaceInValue() {

-        String expectedOutput = "---" + System.lineSeparator();

-        expectedOutput += "root(Type=StringLiteralExpr): " + System.lineSeparator();

-        expectedOutput += "    value: \"a\\\\: b\"" + System.lineSeparator();

-        expectedOutput += "...";

-

-        YamlPrinter yamlPrinter = new YamlPrinter(true);

-        Expression expression = JavaParser.parseExpression("\"a\\\\: b\"");

-        String output = yamlPrinter.output(expression);

-        assertEquals(expectedOutput, output);

-    }

-

-    @Test

-    public void testWithColonFollowedByLineSeparatorInValue() {

-        String expectedOutput = "---" + System.lineSeparator();

-        expectedOutput += "root(Type=StringLiteralExpr): " + System.lineSeparator();

-        expectedOutput += "    value: \"a\\\\:\\\\nb\"" + System.lineSeparator();

-        expectedOutput += "...";

-

-        YamlPrinter yamlPrinter = new YamlPrinter(true);

-        Expression expression = JavaParser.parseExpression("\"a\\\\:\\\\nb\"");

-        String output = yamlPrinter.output(expression);

-        assertEquals(expectedOutput, output);

-    }

-}

diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/AbstractLexicalPreservingTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/AbstractLexicalPreservingTest.java
deleted file mode 100644
index 1088457..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/AbstractLexicalPreservingTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.printer.lexicalpreservation;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.expr.Expression;
-import org.junit.Before;
-
-import java.io.IOException;
-
-import static com.github.javaparser.utils.TestUtils.readResource;
-import static org.junit.Assert.assertEquals;
-
-public abstract class AbstractLexicalPreservingTest {
-
-    protected CompilationUnit cu;
-    protected Expression expression;
-
-    protected void considerCode(String code) {
-        cu = LexicalPreservingPrinter.setup(JavaParser.parse(code));
-    }
-
-    protected void considerExpression(String code) {
-        expression = LexicalPreservingPrinter.setup(JavaParser.parseExpression(code));
-    }
-
-    protected String considerExample(String resourceName) throws IOException {
-        String code = readExample(resourceName);
-        considerCode(code);
-        return code;
-    }
-
-    protected String readExample(String resourceName) throws IOException {
-        return readResource("com/github/javaparser/lexical_preservation_samples/" + resourceName + ".java.txt");
-    }
-
-    protected void assertTransformed(String exampleName, Node node) throws IOException {
-        String expectedCode = readExample(exampleName + "_expected");
-        String actualCode = LexicalPreservingPrinter.print(node);
-        assertEquals(expectedCode, actualCode);
-    }
-
-    protected void assertUnchanged(String exampleName) throws IOException {
-        String code = considerExample(exampleName + "_original");
-        assertEquals(code, LexicalPreservingPrinter.print(cu != null ? cu : expression));
-    }
-
-    protected void assertTransformedToString(String expectedPartialCode, Node node) {
-        String actualCode = LexicalPreservingPrinter.print(node);
-        assertEquals(expectedPartialCode, actualCode);
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/DifferenceTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/DifferenceTest.java
deleted file mode 100644
index 2fb98c1..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/DifferenceTest.java
+++ /dev/null
@@ -1,428 +0,0 @@
-package com.github.javaparser.printer.lexicalpreservation;
-
-import com.github.javaparser.GeneratedJavaParserConstants;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.PackageDeclaration;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.ast.expr.*;
-import com.github.javaparser.ast.observer.ObservableProperty;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.ast.type.ArrayType;
-import com.github.javaparser.ast.type.PrimitiveType;
-import com.github.javaparser.printer.ConcreteSyntaxModel;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmIndent;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmUnindent;
-import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-
-import static com.github.javaparser.TokenTypes.eolTokenKind;
-import static com.github.javaparser.TokenTypes.spaceTokenKind;
-import static com.github.javaparser.printer.lexicalpreservation.Difference.DifferenceElement.*;
-import static org.junit.Assert.assertEquals;
-
-public class DifferenceTest extends AbstractLexicalPreservingTest {
-
-    @Test
-    public void calculateDifferenceEmpty() {
-        LexicalDifferenceCalculator.CalculatedSyntaxModel a = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel b = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
-        Difference diff = Difference.calculate(a, b);
-        assertEquals(0, diff.getElements().size());
-    }
-
-    @Test
-    public void calculateDifferenceAIsEmpty() {
-        Node n1 = new FieldDeclaration();
-        Node n2 = new MethodDeclaration();
-
-        LexicalDifferenceCalculator.CalculatedSyntaxModel a = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel b = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Arrays.asList(
-                new CsmToken(GeneratedJavaParserConstants.LPAREN),
-                new CsmChild(n1),
-                new CsmToken(GeneratedJavaParserConstants.RPAREN),
-                new CsmChild(n2)));
-        Difference diff = Difference.calculate(a, b);
-        assertEquals(4, diff.getElements().size());
-        assertEquals(added(new CsmToken(GeneratedJavaParserConstants.LPAREN)), diff.getElements().get(0));
-        assertEquals(added(new CsmChild(n1)), diff.getElements().get(1));
-        assertEquals(added(new CsmToken(GeneratedJavaParserConstants.RPAREN)), diff.getElements().get(2));
-        assertEquals(added(new CsmChild(n2)), diff.getElements().get(3));
-    }
-
-    @Test
-    public void calculateDifferenceBIsEmpty() {
-        Node n1 = new FieldDeclaration();
-        Node n2 = new MethodDeclaration();
-
-        LexicalDifferenceCalculator.CalculatedSyntaxModel a = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Arrays.asList(
-                new CsmToken(GeneratedJavaParserConstants.LPAREN),
-                new CsmChild(n1),
-                new CsmToken(GeneratedJavaParserConstants.RPAREN),
-                new CsmChild(n2)));
-        LexicalDifferenceCalculator.CalculatedSyntaxModel b = new LexicalDifferenceCalculator.CalculatedSyntaxModel(Collections.emptyList());
-        Difference diff = Difference.calculate(a, b);
-        assertEquals(4, diff.getElements().size());
-        assertEquals(removed(new CsmToken(GeneratedJavaParserConstants.LPAREN)), diff.getElements().get(0));
-        assertEquals(removed(new CsmChild(n1)), diff.getElements().get(1));
-        assertEquals(removed(new CsmToken(GeneratedJavaParserConstants.RPAREN)), diff.getElements().get(2));
-        assertEquals(removed(new CsmChild(n2)), diff.getElements().get(3));
-    }
-
-    @Test
-    public void compilationUnitExampleWithPackageSetDiff() {
-        considerCode("class A {}");
-        CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
-        PackageDeclaration packageDeclaration = new PackageDeclaration(new Name(new Name("foo"), "bar"));
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, cu);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, cu, ObservableProperty.PACKAGE_DECLARATION, null, packageDeclaration);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        assertEquals(3, diff.getElements().size());
-        assertEquals(added(new CsmChild(packageDeclaration)), diff.getElements().get(0));
-        assertEquals(kept(new CsmChild(cu.getType(0))), diff.getElements().get(1));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(2));
-    }
-
-    @Test
-    public void annotationDeclarationExampleWithModifierAdded() throws IOException {
-        considerExample("AnnotationDeclaration_Example1_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.MODIFIERS, EnumSet.noneOf(Modifier.class), EnumSet.of(Modifier.PUBLIC));
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        diff.removeIndentationElements();
-        int i = 0;
-        assertEquals(added(new CsmToken(GeneratedJavaParserConstants.PUBLIC)), diff.getElements().get(i++));
-        assertEquals(added(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void annotationDeclarationExampleWithNameChanged() throws IOException {
-        considerExample("AnnotationDeclaration_Example1_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
-        SimpleName newName = new SimpleName("NewName");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.NAME,
-                annotationDeclaration.getName(), newName);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        diff.removeIndentationElements();
-        int i = 0;
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(removed(new CsmChild(annotationDeclaration.getName())), diff.getElements().get(i++));
-        assertEquals(added(new CsmChild(newName)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void annotationDeclarationExampleWithJavadocAdded() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        JavadocComment comment = new JavadocComment("Cool this annotation!");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.COMMENT, null, comment);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        diff.removeIndentationElements();
-        int i = 0;
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.PUBLIC)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void annotationDeclarationExampleWithJavadocRemoved() throws IOException {
-        considerExample("AnnotationDeclaration_Example9_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.COMMENT, annotationDeclaration.getComment().get(), null);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        diff.removeIndentationElements();
-        int i = 0;
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.PUBLIC)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void annotationDeclarationExampleWithModifierRemoved() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.MODIFIERS, EnumSet.of(Modifier.PUBLIC), EnumSet.noneOf(Modifier.class));
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        diff.removeIndentationElements();
-        int i = 0;
-        assertEquals(removed(new CsmToken(GeneratedJavaParserConstants.PUBLIC)), diff.getElements().get(i++));
-        assertEquals(removed(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.AT)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.INTERFACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getName())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(0))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(1))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(2))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(3))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(4))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(annotationDeclaration.getMember(5))), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void removeDefaultValueInAnnotationMemberDeclaration() {
-        AnnotationMemberDeclaration md = considerAmd("int foo() default 10;");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(md, ObservableProperty.DEFAULT_VALUE, md.getDefaultValue(), null);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        int i = 0;
-        assertEquals(kept(new CsmChild(md.getType())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(md.getName())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), diff.getElements().get(i++));
-        assertEquals(removed(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(removed(new CsmToken(GeneratedJavaParserConstants._DEFAULT)), diff.getElements().get(i++));
-        assertEquals(removed(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(removed(new CsmChild(md.getDefaultValue().get())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.SEMICOLON)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void addedDefaultValueInAnnotationMemberDeclaration() {
-        AnnotationMemberDeclaration md = considerAmd("int foo();");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
-        Expression defaultValue = new IntegerLiteralExpr(("10"));
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(md, ObservableProperty.DEFAULT_VALUE, null, defaultValue);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        int i = 0;
-        assertEquals(kept(new CsmChild(md.getType())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(md.getName())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), diff.getElements().get(i++));
-        assertEquals(added(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(added(new CsmToken(GeneratedJavaParserConstants._DEFAULT)), diff.getElements().get(i++));
-        assertEquals(added(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(added(new CsmChild(defaultValue)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.SEMICOLON)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void addedModifierToConstructorDeclaration() {
-        ConstructorDeclaration cd = considerCd("A(){}");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(cd);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(cd, ObservableProperty.MODIFIERS,
-                EnumSet.noneOf(Modifier.class), EnumSet.of(Modifier.PUBLIC));
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        int i = 0;
-        assertEquals(added(new CsmToken(GeneratedJavaParserConstants.PUBLIC)), diff.getElements().get(i++));
-        assertEquals(added(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(cd.getName())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), diff.getElements().get(i++));
-        assertEquals(kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(kept(new CsmChild(cd.getBody())), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void replacingNameForEnumConstantDeclaration() throws IOException {
-        EnumConstantDeclaration ecd = considerEcd("A");
-        SimpleName newName = new SimpleName("B");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(ecd);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(ecd, ObservableProperty.NAME,
-                ecd.getName(), newName);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        int i = 0;
-        assertEquals(Difference.DifferenceElement.removed(new CsmChild(ecd.getName())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.added(new CsmChild(newName)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void addingStatementToEmptyMethodBody() {
-        String code = "class A { void foo(char p1, int p2) {} }";
-        considerCode(code);
-
-        Statement s = new ExpressionStmt(new BinaryExpr(
-                new IntegerLiteralExpr("10"), new IntegerLiteralExpr("2"), BinaryExpr.Operator.PLUS
-        ));
-        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(m.getBody().get());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterListAddition(m.getBody().get(), ObservableProperty.STATEMENTS, 0, s);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        int i = 0;
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.added(new CsmIndent()), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.added(new CsmChild(s)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.added(new CsmToken(eolTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.added(new CsmUnindent()), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void methodDeclarationRemovingParameter() {
-        MethodDeclaration md = considerMd("public void foo(float f){}");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterListRemoval(md, ObservableProperty.PARAMETERS, 0);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        int i = 0;
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.PUBLIC)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmChild(md.getType())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmChild(md.getName())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.removed(new CsmChild(md.getParameter(0))), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmChild(md.getBody().get())), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    @Test
-    public void methodDeclarationAddingParameter() {
-        MethodDeclaration md = considerMd("public void foo(){}");
-        Parameter newParameter = new Parameter(new ArrayType(PrimitiveType.intType()), new SimpleName("foo"));
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(md);
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterListAddition(md, ObservableProperty.PARAMETERS, 0, newParameter);
-        Difference diff = Difference.calculate(csmOriginal, csmChanged);
-        int i = 0;
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.PUBLIC)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmChild(md.getType())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmChild(md.getName())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.LPAREN)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.added(new CsmChild(newParameter)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(GeneratedJavaParserConstants.RPAREN)), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmToken(spaceTokenKind())), diff.getElements().get(i++));
-        assertEquals(Difference.DifferenceElement.kept(new CsmChild(md.getBody().get())), diff.getElements().get(i++));
-        assertEquals(i, diff.getElements().size());
-    }
-
-    private AnnotationMemberDeclaration considerAmd(String code) {
-        considerCode("@interface AD { " + code + " }");
-        return (AnnotationMemberDeclaration)cu.getAnnotationDeclarationByName("AD").get().getMember(0);
-    }
-
-    private ConstructorDeclaration considerCd(String code) {
-        considerCode("class A { " + code + " }");
-        return (ConstructorDeclaration) cu.getType(0).getMembers().get(0);
-    }
-
-    private EnumConstantDeclaration considerEcd(String code) {
-        considerCode("enum A { " + code + " }");
-        return ((EnumDeclaration)cu.getType(0)).getEntries().get(0);
-    }
-
-    private MethodDeclaration considerMd(String code) {
-        considerCode("class A { " + code + " }");
-        return (MethodDeclaration) cu.getType(0).getMembers().get(0);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculatorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculatorTest.java
deleted file mode 100644
index d3e5490..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculatorTest.java
+++ /dev/null
@@ -1,300 +0,0 @@
-package com.github.javaparser.printer.lexicalpreservation;
-
-import com.github.javaparser.GeneratedJavaParserConstants;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.PackageDeclaration;
-import com.github.javaparser.ast.body.AnnotationDeclaration;
-import com.github.javaparser.ast.body.EnumConstantDeclaration;
-import com.github.javaparser.ast.body.EnumDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.ast.expr.*;
-import com.github.javaparser.ast.observer.ObservableProperty;
-import com.github.javaparser.ast.stmt.BlockStmt;
-import com.github.javaparser.ast.stmt.ExpressionStmt;
-import com.github.javaparser.ast.stmt.Statement;
-import com.github.javaparser.printer.ConcreteSyntaxModel;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
-import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-import static com.github.javaparser.TokenTypes.eolTokenKind;
-import static com.github.javaparser.TokenTypes.spaceTokenKind;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class LexicalDifferenceCalculatorTest extends AbstractLexicalPreservingTest {
-
-    @Test
-    public void compilationUnitExampleOriginal() {
-        considerCode("class A {}");
-        CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, cu);
-        assertEquals(2, csmOriginal.elements.size());
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(cu.getType(0)), csmOriginal.elements.get(0));
-        assertEquals(new CsmToken(eolTokenKind()), csmOriginal.elements.get(1));
-    }
-
-    @Test
-    public void compilationUnitExampleWithPackageSet() {
-        considerCode("class A {}");
-        CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
-        PackageDeclaration packageDeclaration = new PackageDeclaration(new Name(new Name("foo"), "bar"));
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, cu, ObservableProperty.PACKAGE_DECLARATION, null, packageDeclaration);
-        assertEquals(3, csmChanged.elements.size());
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(packageDeclaration), csmChanged.elements.get(0));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(cu.getType(0)), csmChanged.elements.get(1));
-        assertEquals(new CsmToken(eolTokenKind()), csmChanged.elements.get(2));
-    }
-
-    @Test
-    public void annotationDeclarationModifiersExampleOriginal() throws IOException {
-        considerExample("AnnotationDeclaration_Example1_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
-        csm.removeIndentationElements();
-        int i = 0;
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
-        assertEquals(i, csm.elements.size());
-    }
-
-    @Test
-    public void annotationDeclarationModifiersExampleModified() throws IOException {
-        considerExample("AnnotationDeclaration_Example1_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.MODIFIERS, EnumSet.noneOf(Modifier.class), EnumSet.of(Modifier.PUBLIC));
-        csm.removeIndentationElements();
-        int i = 0;
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.PUBLIC), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
-        assertEquals(i, csm.elements.size());
-    }
-
-    @Test
-    public void annotationDeclarationNameExampleModified() throws IOException {
-        considerExample("AnnotationDeclaration_Example1_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        SimpleName newName = new SimpleName("NewName");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.NAME,
-                annotationDeclaration.getName(), newName);
-        csm.removeIndentationElements();
-        int i = 0;
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(newName), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
-        assertEquals(i, csm.elements.size());
-    }
-
-    @Test
-    public void annotationDeclaratioJavadocExampleOriginal() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
-        csm.removeIndentationElements();
-        int i = 0;
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.PUBLIC), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
-        assertEquals(i, csm.elements.size());
-    }
-
-    @Test
-    public void annotationDeclaratioJavadocExampleAddingJavadoc() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
-        CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
-        JavadocComment comment = new JavadocComment("Cool this annotation!");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.COMMENT, null, comment);
-        csm.removeIndentationElements();
-        int i = 0;
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.PUBLIC), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
-        assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
-        assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
-        assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
-        assertEquals(i, csm.elements.size());
-    }
-
-    @Test
-    public void simpleEnumConstantDeclaration() throws IOException {
-        EnumConstantDeclaration ecd = considerEcd("A");
-        LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(ecd);
-
-        int i = 0;
-        assertEquals(new LexicalDifferenceCalculator.CsmChild(ecd.getName()), csm.elements.get(i++));
-        assertEquals(i, csm.elements.size());
-    }
-
-    @Test
-    public void csmModelAfterAddingStatementToEmptyBlock() throws IOException {
-        LexicalDifferenceCalculator ldc = new LexicalDifferenceCalculator();
-        considerExample("ASimpleClassWithMoreFormatting_step3");
-
-        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
-                .getMethodsByName("setAField").get(0);
-        Statement assignStatement = new ExpressionStmt(
-                new AssignExpr(
-                        new FieldAccessExpr(new ThisExpr(),"aField"),
-                        new NameExpr("aField"),
-                        AssignExpr.Operator.ASSIGN
-                ));
-        LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel =
-                ldc.calculatedSyntaxModelAfterListAddition(
-                        ConcreteSyntaxModel.forClass(BlockStmt.class),
-                        ObservableProperty.STATEMENTS,
-                        setter.getBody().get().getStatements(),
-                        0,
-                        assignStatement);
-        int index = 0;
-        assertEquals(CsmElement.token(GeneratedJavaParserConstants.LBRACE), calculatedSyntaxModel.elements.get(index++));
-        assertEquals(CsmElement.newline(), calculatedSyntaxModel.elements.get(index++));
-        assertEquals(CsmElement.indent(), calculatedSyntaxModel.elements.get(index++));
-        assertTrue(isChild(calculatedSyntaxModel.elements.get(index++), ExpressionStmt.class));
-        assertEquals(CsmElement.newline(), calculatedSyntaxModel.elements.get(index++));
-        assertEquals(CsmElement.unindent(), calculatedSyntaxModel.elements.get(index++));
-        assertEquals(CsmElement.token(GeneratedJavaParserConstants.RBRACE), calculatedSyntaxModel.elements.get(index++));
-        assertEquals(index, calculatedSyntaxModel.elements.size());
-    }
-
-    @Test
-    public void differenceAfterddingStatementToEmptyBlock() throws IOException {
-        LexicalDifferenceCalculator ldc = new LexicalDifferenceCalculator();
-        considerExample("ASimpleClassWithMoreFormatting_step3");
-
-        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
-                .getMethodsByName("setAField").get(0);
-        Statement assignStatement = new ExpressionStmt(
-                new AssignExpr(
-                        new FieldAccessExpr(new ThisExpr(),"aField"),
-                        new NameExpr("aField"),
-                        AssignExpr.Operator.ASSIGN
-                ));
-        Difference diff = ldc.calculateListAdditionDifference(
-                ObservableProperty.STATEMENTS,
-                setter.getBody().get().getStatements(),
-                0,
-                assignStatement);
-        int index = 0;
-        assertEquals(Difference.DifferenceElement.kept(CsmElement.token(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(index++));
-        assertEquals(Difference.DifferenceElement.kept(CsmElement.newline()), diff.getElements().get(index++));
-        assertEquals(Difference.DifferenceElement.added(CsmElement.indent()), diff.getElements().get(index++));
-        assertTrue(isAddedChild(diff.getElements().get(index++), ExpressionStmt.class));
-        assertEquals(Difference.DifferenceElement.added(CsmElement.newline()), diff.getElements().get(index++));
-        assertEquals(Difference.DifferenceElement.added(CsmElement.unindent()), diff.getElements().get(index++));
-        assertEquals(Difference.DifferenceElement.kept(CsmElement.token(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(index++));
-        assertEquals(index, diff.getElements().size());
-    }
-
-    private boolean isAddedChild(Difference.DifferenceElement element, Class<? extends Node> childClass) {
-        return element.isAdded() && isChild(element.getElement(), childClass);
-    }
-
-    private boolean isChild(CsmElement element, Class<? extends Node> childClass) {
-        return element instanceof LexicalDifferenceCalculator.CsmChild && childClass.isInstance(((LexicalDifferenceCalculator.CsmChild)element).getChild());
-    }
-
-    protected EnumConstantDeclaration considerEcd(String code) {
-        considerCode("enum A { " + code + " }");
-        return ((EnumDeclaration)cu.getType(0)).getEntries().get(0);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java
deleted file mode 100644
index 796da14..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/LexicalPreservingPrinterTest.java
+++ /dev/null
@@ -1,1051 +0,0 @@
-package com.github.javaparser.printer.lexicalpreservation;
-
-import com.github.javaparser.*;
-import com.github.javaparser.ast.*;
-import com.github.javaparser.ast.body.*;
-import com.github.javaparser.ast.expr.*;
-import com.github.javaparser.ast.stmt.*;
-import com.github.javaparser.ast.type.Type;
-import com.github.javaparser.ast.type.UnionType;
-import com.github.javaparser.ast.type.VoidType;
-import com.github.javaparser.ast.visitor.ModifierVisitor;
-import com.github.javaparser.ast.visitor.Visitable;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter.NODE_TEXT_DATA;
-import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol;
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class LexicalPreservingPrinterTest extends AbstractLexicalPreservingTest {
-    private NodeText getTextForNode(Node node) {
-        return node.getData(NODE_TEXT_DATA);
-    }
-
-
-    //
-    // Tests on TextNode definition
-    //
-
-    @Test
-    public void checkNodeTextCreatedForSimplestClass() {
-        considerCode("class A {}");
-
-        // CU
-        assertEquals(1, getTextForNode(cu).numberOfElements());
-        assertEquals(true, getTextForNode(cu).getTextElement(0) instanceof ChildTextElement);
-        assertEquals(cu.getClassByName("A").get(), ((ChildTextElement)getTextForNode(cu).getTextElement(0)).getChild());
-
-        // Class
-        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
-        assertEquals(7, getTextForNode(classA).numberOfElements());
-        assertEquals("class", getTextForNode(classA).getTextElement(0).expand());
-        assertEquals(" ", getTextForNode(classA).getTextElement(1).expand());
-        assertEquals("A", getTextForNode(classA).getTextElement(2).expand());
-        assertEquals(" ", getTextForNode(classA).getTextElement(3).expand());
-        assertEquals("{", getTextForNode(classA).getTextElement(4).expand());
-        assertEquals("}", getTextForNode(classA).getTextElement(5).expand());
-        assertEquals("", getTextForNode(classA).getTextElement(6).expand());
-        assertEquals(true, getTextForNode(classA).getTextElement(6) instanceof TokenTextElement);
-        assertEquals(GeneratedJavaParserConstants.EOF, ((TokenTextElement)getTextForNode(classA).getTextElement(6)).getTokenKind());
-    }
-
-    @Test
-    public void checkNodeTextCreatedForField() {
-        String code = "class A {int i;}";
-        considerCode(code);
-
-        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
-        FieldDeclaration fd = classA.getFieldByName("i").get();
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(fd);
-        assertEquals(Arrays.asList("int", " ", "i", ";"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedForVariableDeclarator() {
-        String code = "class A {int i;}";
-        considerCode(code);
-
-        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
-        FieldDeclaration fd = classA.getFieldByName("i").get();
-        VariableDeclarator vd = fd.getVariables().get(0);
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(vd);
-        assertEquals(Arrays.asList("i"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedForMethod() {
-        String code = "class A {void foo(int p1, float p2) { }}";
-        considerCode(code);
-
-        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
-        MethodDeclaration md = classA.getMethodsByName("foo").get(0);
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
-        assertEquals(Arrays.asList("void", " ", "foo", "(", "int p1", ",", " ", "float p2", ")", " ", "{ }"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedForMethodParameter() {
-        String code = "class A {void foo(int p1, float p2) { }}";
-        considerCode(code);
-
-        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
-        MethodDeclaration md = classA.getMethodsByName("foo").get(0);
-        Parameter p1 = md.getParameterByName("p1").get();
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(p1);
-        assertEquals(Arrays.asList("int", " ", "p1"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedForPrimitiveType() {
-        String code = "class A {void foo(int p1, float p2) { }}";
-        considerCode(code);
-
-        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
-        MethodDeclaration md = classA.getMethodsByName("foo").get(0);
-        Parameter p1 = md.getParameterByName("p1").get();
-        Type t = p1.getType();
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(t);
-        assertEquals(Arrays.asList("int"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedForSimpleImport() {
-        String code = "import a.b.c.D;";
-        considerCode(code);
-
-        ImportDeclaration imp = (ImportDeclaration)cu.getChildNodes().get(0);
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(imp);
-        assertEquals(Arrays.asList("import", " ", "a.b.c.D", ";", ""),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedGenericType() {
-        String code = "class A {ParseResult<T> result;}";
-        considerCode(code);
-
-        FieldDeclaration field = cu.getClassByName("A").get().getFieldByName("result").get();
-        Node t = field.getCommonType();
-        Node t2 = field.getVariable(0).getType();
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(field);
-        assertEquals(Arrays.asList("ParseResult", "<", "T", ">", " ", "result", ";"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedAnnotationDeclaration() {
-        String code = "public @interface ClassPreamble { String author(); }";
-        considerCode(code);
-
-        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(ad);
-        assertEquals(Arrays.asList("public", " ", "@", "interface", " ", "ClassPreamble", " ", "{", " ", "String author();", " ", "}", ""),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedAnnotationMemberDeclaration() {
-        String code = "public @interface ClassPreamble { String author(); }";
-        considerCode(code);
-
-        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
-        AnnotationMemberDeclaration md = (AnnotationMemberDeclaration)ad.getMember(0);
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
-        assertEquals(Arrays.asList("String", " ", "author", "(", ")", ";"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedAnnotationMemberDeclarationWithArrayType() {
-        String code = "public @interface ClassPreamble { String[] author(); }";
-        considerCode(code);
-
-        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
-        AnnotationMemberDeclaration md = (AnnotationMemberDeclaration)ad.getMember(0);
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
-        assertEquals(Arrays.asList("String[]", " ", "author", "(", ")", ";"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedAnnotationMemberDeclarationArrayType() {
-        String code = "public @interface ClassPreamble { String[] author(); }";
-        considerCode(code);
-
-        AnnotationDeclaration ad = cu.getAnnotationDeclarationByName("ClassPreamble").get();
-        AnnotationMemberDeclaration md = (AnnotationMemberDeclaration)ad.getMember(0).asAnnotationMemberDeclaration();
-        Type type = md.getType();
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(type);
-        assertEquals(Arrays.asList("String", "[", "]"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedAnnotationMemberDeclarationWithComment() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-
-        AnnotationMemberDeclaration md = (AnnotationMemberDeclaration)cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(5).asAnnotationMemberDeclaration();
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(md);
-        assertEquals(Arrays.asList("String[]", " ", "reviewers", "(", ")", ";"),
-                nodeText.getElements().stream().map(TextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedArrayCreationLevelWithoutExpression() throws IOException {
-        considerExpression("new int[]");
-
-        ArrayCreationExpr arrayCreationExpr = (ArrayCreationExpr)expression.asArrayCreationExpr();
-        ArrayCreationLevel arrayCreationLevel = arrayCreationExpr.getLevels().get(0);
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(arrayCreationLevel);
-        assertEquals(Arrays.asList("[", "]"),
-                nodeText.getElements().stream().map(TextElement::expand).filter(e -> !e.isEmpty()).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void checkNodeTextCreatedArrayCreationLevelWith() throws IOException {
-        considerExpression("new int[123]");
-
-        ArrayCreationExpr arrayCreationExpr = (ArrayCreationExpr)expression.asArrayCreationExpr();
-        ArrayCreationLevel arrayCreationLevel = arrayCreationExpr.getLevels().get(0);
-        NodeText nodeText = LexicalPreservingPrinter.getOrCreateNodeText(arrayCreationLevel);
-        assertEquals(Arrays.asList("[", "123", "]"),
-                nodeText.getElements().stream().map(TextElement::expand).filter(e -> !e.isEmpty()).collect(Collectors.toList()));
-    }
-
-    //
-    // Tests on findIndentation
-    //
-
-    @Test
-    public void findIndentationForAnnotationMemberDeclarationWithoutComment() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        Node node = cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(4);
-        List<TokenTextElement> indentation = LexicalPreservingPrinter.findIndentation(node);
-        assertEquals(Arrays.asList(" ", " ", " "), indentation.stream().map(TokenTextElement::expand).collect(Collectors.toList()));
-    }
-
-    @Test
-    public void findIndentationForAnnotationMemberDeclarationWithComment() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        Node node = cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(5);
-        List<TokenTextElement> indentation = LexicalPreservingPrinter.findIndentation(node);
-        assertEquals(Arrays.asList(" ", " ", " "), indentation.stream().map(TokenTextElement::expand).collect(Collectors.toList()));
-    }
-
-    //
-    // Tests on printing
-    //
-
-    @Test
-    public void printASuperSimpleCUWithoutChanges() {
-        String code = "class A {}";
-        considerCode(code);
-
-        assertEquals(code, LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void printASuperSimpleClassWithAFieldAdded() {
-        String code = "class A {}";
-        considerCode(code);
-
-        ClassOrInterfaceDeclaration classA = cu.getClassByName("A").get();
-        classA.addField("int", "myField");
-        assertEquals("class A {" + EOL + "    int myField;"+EOL+"}", LexicalPreservingPrinter.print(classA));
-    }
-
-    @Test
-    public void printASuperSimpleClassWithoutChanges() {
-        String code = "class A {}";
-        considerCode(code);
-
-        assertEquals(code, LexicalPreservingPrinter.print(cu.getClassByName("A").get()));
-    }
-
-    @Test
-    public void printASimpleCUWithoutChanges() {
-        String code = "class /*a comment*/ A {\t\t"+EOL+" int f;"+EOL+EOL+EOL+"         void foo(int p  ) { return  'z'  \t; }}";
-        considerCode(code);
-
-        assertEquals(code, LexicalPreservingPrinter.print(cu));
-        assertEquals(code, LexicalPreservingPrinter.print(cu.getClassByName("A").get()));
-        assertEquals("void foo(int p  ) { return  'z'  \t; }", LexicalPreservingPrinter.print(cu.getClassByName("A").get().getMethodsByName("foo").get(0)));
-    }
-
-    @Test
-    public void printASimpleClassRemovingAField() {
-        String code = "class /*a comment*/ A {\t\t"+EOL+" int f;"+EOL+EOL+EOL+"         void foo(int p  ) { return  'z'  \t; }}";
-        considerCode(code);
-
-        ClassOrInterfaceDeclaration c = cu.getClassByName("A").get();
-        c.getMembers().remove(0);
-        assertEquals("class /*a comment*/ A {\t\t"+ EOL +
-                EOL +
-                "         void foo(int p  ) { return  'z'  \t; }}", LexicalPreservingPrinter.print(c));
-    }
-
-    @Test
-    public void printASimpleMethodAddingAParameterToAMethodWithZeroParameters() {
-        String code = "class A { void foo() {} }";
-        considerCode(code);
-
-        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
-        m.addParameter("float", "p1");
-        assertEquals("void foo(float p1) {}", LexicalPreservingPrinter.print(m));
-    }
-
-    @Test
-    public void printASimpleMethodAddingAParameterToAMethodWithOneParameter() {
-        String code = "class A { void foo(char p1) {} }";
-        considerCode(code);
-
-        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
-        m.addParameter("float", "p2");
-        assertEquals("void foo(char p1, float p2) {}", LexicalPreservingPrinter.print(m));
-    }
-
-    @Test
-    public void printASimpleMethodRemovingAParameterToAMethodWithOneParameter() {
-        String code = "class A { void foo(float p1) {} }";
-        considerCode(code);
-
-        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
-        m.getParameters().remove(0);
-        assertEquals("void foo() {}", LexicalPreservingPrinter.print(m));
-    }
-
-    @Test
-    public void printASimpleMethodRemovingParameterOneFromMethodWithTwoParameters() {
-        String code = "class A { void foo(char p1, int p2) {} }";
-        considerCode(code);
-
-        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
-        m.getParameters().remove(0);
-        assertEquals("void foo(int p2) {}", LexicalPreservingPrinter.print(m));
-    }
-
-    @Test
-    public void printASimpleMethodRemovingParameterTwoFromMethodWithTwoParameters() {
-        String code = "class A { void foo(char p1, int p2) {} }";
-        considerCode(code);
-
-        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
-        m.getParameters().remove(1);
-        assertEquals("void foo(char p1) {}", LexicalPreservingPrinter.print(m));
-    }
-
-    @Test
-    public void printASimpleMethodAddingAStatement() {
-        String code = "class A { void foo(char p1, int p2) {} }";
-        considerCode(code);
-
-        Statement s = new ExpressionStmt(new BinaryExpr(
-                new IntegerLiteralExpr("10"), new IntegerLiteralExpr("2"), BinaryExpr.Operator.PLUS
-        ));
-        NodeList<Statement> stmts = cu.getClassByName("A").get().getMethodsByName("foo").get(0).getBody().get().getStatements();
-        stmts.add(s);
-        MethodDeclaration m = cu.getClassByName("A").get().getMethodsByName("foo").get(0);
-        assertEquals("void foo(char p1, int p2) {"+EOL +
-                "    10 + 2;"+ EOL +
-                "}", LexicalPreservingPrinter.print(m));
-    }
-
-    @Test
-    public void printASimpleImport() {
-        String code = "import a.b.c.D;";
-        considerCode(code);
-
-        ImportDeclaration imp = (ImportDeclaration)cu.getChildNodes().get(0);
-        assertEquals("import a.b.c.D;", LexicalPreservingPrinter.print(imp));
-    }
-
-    @Test
-    public void printAnotherImport() {
-        String code = "import com.github.javaparser.ast.CompilationUnit;";
-        considerCode(code);
-
-        ImportDeclaration imp = (ImportDeclaration)cu.getChildNodes().get(0);
-        assertEquals("import com.github.javaparser.ast.CompilationUnit;", LexicalPreservingPrinter.print(imp));
-    }
-
-    @Test
-    public void printAStaticImport() {
-        String code = "import static com.github.javaparser.ParseStart.*;";
-        considerCode(code);
-
-        ImportDeclaration imp = (ImportDeclaration)cu.getChildNodes().get(0);
-        assertEquals("import static com.github.javaparser.ParseStart.*;", LexicalPreservingPrinter.print(imp));
-    }
-
-    @Test
-    public void checkAnnidatedTypeParametersPrinting() {
-        String code = "class A { private final Stack<Iterator<Triple>> its = new Stack<Iterator<Triple>>(); }";
-        considerCode(code);
-        assertEquals("class A { private final Stack<Iterator<Triple>> its = new Stack<Iterator<Triple>>(); }", LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void printASingleCatch() {
-        String code = "class A {{try { doit(); } catch (Exception e) {}}}";
-        considerCode(code);
-
-        assertEquals("class A {{try { doit(); } catch (Exception e) {}}}", LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void printAMultiCatch() {
-        String code = "class A {{try { doit(); } catch (Exception | AssertionError e) {}}}";
-        considerCode(code);
-
-        assertEquals("class A {{try { doit(); } catch (Exception | AssertionError e) {}}}", LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void printASingleCatchType() {
-        String code = "class A {{try { doit(); } catch (Exception e) {}}}";
-        considerCode(code);
-        InitializerDeclaration initializerDeclaration = (InitializerDeclaration)cu.getType(0).getMembers().get(0);
-        TryStmt tryStmt = (TryStmt)initializerDeclaration.getBody().getStatements().get(0);
-        CatchClause catchClause = tryStmt.getCatchClauses().get(0);
-        Type catchType = catchClause.getParameter().getType();
-
-        assertEquals("Exception", LexicalPreservingPrinter.print(catchType));
-    }
-
-    @Test
-    public void printUnionType() {
-        String code = "class A {{try { doit(); } catch (Exception | AssertionError e) {}}}";
-        considerCode(code);
-        InitializerDeclaration initializerDeclaration = (InitializerDeclaration)cu.getType(0).getMembers().get(0);
-        TryStmt tryStmt = (TryStmt)initializerDeclaration.getBody().getStatements().get(0);
-        CatchClause catchClause = tryStmt.getCatchClauses().get(0);
-        UnionType unionType = (UnionType)catchClause.getParameter().getType();
-
-        assertEquals("Exception | AssertionError", LexicalPreservingPrinter.print(unionType));
-    }
-
-    @Test
-    public void printParameterHavingUnionType() {
-        String code = "class A {{try { doit(); } catch (Exception | AssertionError e) {}}}";
-        considerCode(code);
-        InitializerDeclaration initializerDeclaration = (InitializerDeclaration)cu.getType(0).getMembers().get(0);
-        TryStmt tryStmt = (TryStmt)initializerDeclaration.getBody().getStatements().get(0);
-        CatchClause catchClause = tryStmt.getCatchClauses().get(0);
-        Parameter parameter = catchClause.getParameter();
-
-        assertEquals("Exception | AssertionError e", LexicalPreservingPrinter.print(parameter));
-    }
-
-    @Test
-    public void printLambaWithUntypedParams() {
-        String code = "class A {Function<String,String> f = a -> a;}";
-        considerCode(code);
-
-        assertEquals("class A {Function<String,String> f = a -> a;}", LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void printAModuleInfoSpecificKeywordUsedAsIdentifier1() {
-        considerCode("class module { }");
-
-        cu.getClassByName("module").get().setName("xyz");
-
-        assertEquals("class xyz { }", LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void printAModuleInfoSpecificKeywordUsedAsIdentifier2() {
-        considerCode("class xyz { }");
-
-        cu.getClassByName("xyz").get().setName("module");
-
-        assertEquals("class module { }", LexicalPreservingPrinter.print(cu));
-    }
-
-    // Issue 823: setPackageDeclaration on CU starting with a comment
-    @Test
-    public void reactToSetPackageDeclarationOnCuStartingWithComment() {
-        considerCode("// Hey, this is a comment\n" +
-                "\n" +
-                "\n" +
-                "// Another one\n" +
-                "\n" +
-                "class A {}");
-        cu.setPackageDeclaration("org.javaparser.lexicalpreservation.examples");
-    }
-
-    @Test
-    public void printLambdaIntersectionTypeAssignment() {
-        String code = "class A {" + EOL +
-                "  void f() {" + EOL +
-                "    Runnable r = (Runnable & Serializable) (() -> {});" + EOL +
-                "    r = (Runnable & Serializable)() -> {};" + EOL +
-                "    r = (Runnable & I)() -> {};" + EOL +
-                "  }}";
-        considerCode(code);
-
-        assertEquals(code, LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void printLambdaIntersectionTypeReturn() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        considerCode(code);
-
-        assertEquals(code, LexicalPreservingPrinter.print(cu));
-    }
-
-    // See issue #855
-    @Test
-    public void handleOverrideAnnotation() {
-        String code = "public class TestPage extends Page {" + EOL +
-                EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes()
-                .forEach(type -> type.getMembers()
-                        .forEach(member -> {
-                            if (member instanceof MethodDeclaration) {
-                                MethodDeclaration methodDeclaration = (MethodDeclaration) member;
-                                if (!methodDeclaration.getAnnotationByName("Override").isPresent()) {
-                                    methodDeclaration.addAnnotation("Override");
-                                }
-                            }
-                        }));
-        assertEquals("public class TestPage extends Page {" + EOL +
-                EOL +
-                "   @Override()" + EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}", LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void preserveSpaceAsIsForASimpleClassWithMoreFormatting() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting");
-        assertEquals(readExample("ASimpleClassWithMoreFormatting"), LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void renameASimpleClassWithMoreFormatting() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting");
-
-        cu.getClassByName("ASimpleClass").get()
-                .setName("MyRenamedClass");
-        assertEquals(readExample("ASimpleClassWithMoreFormatting_step1"), LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void theLexicalPreservationStringForAnAddedMethodShouldBeIndented() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting");
-
-        cu.getClassByName("ASimpleClass").get()
-                .setName("MyRenamedClass");
-        MethodDeclaration setter = cu
-                .getClassByName("MyRenamedClass").get()
-                .addMethod("setAField", Modifier.PUBLIC);
-        assertEquals("public void setAField() {" + EOL +
-                "    }", LexicalPreservingPrinter.print(setter));
-    }
-
-    @Test
-    public void addMethodToASimpleClassWithMoreFormatting() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting");
-
-        cu.getClassByName("ASimpleClass").get()
-                .setName("MyRenamedClass");
-        MethodDeclaration setter = cu
-                .getClassByName("MyRenamedClass").get()
-                .addMethod("setAField", Modifier.PUBLIC);
-        assertEquals(readExample("ASimpleClassWithMoreFormatting_step2"), LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void addingParameterToAnAddedMethodInASimpleClassWithMoreFormatting() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting");
-
-        cu.getClassByName("ASimpleClass").get()
-                .setName("MyRenamedClass");
-        MethodDeclaration setter = cu
-                .getClassByName("MyRenamedClass").get()
-                .addMethod("setAField", Modifier.PUBLIC);
-        setter.addParameter("boolean", "aField");
-        assertEquals(readExample("ASimpleClassWithMoreFormatting_step3"), LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void findIndentationOfEmptyMethod() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting_step3");
-
-        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
-                .getMethodsByName("setAField").get(0);
-        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter).size());
-        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter.getBody().get()).size());
-    }
-
-    @Test
-    public void findIndentationOfMethodWithStatements() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting_step4");
-
-        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
-                .getMethodsByName("setAField").get(0);
-        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter).size());
-        assertEquals(4, LexicalPreservingPrinter.findIndentation(setter.getBody().get()).size());
-        assertEquals(8, LexicalPreservingPrinter.findIndentation(setter.getBody().get().getStatement(0)).size());
-    }
-
-    @Test
-    public void addingStatementToAnAddedMethodInASimpleClassWithMoreFormatting() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting");
-
-        cu.getClassByName("ASimpleClass").get()
-                .setName("MyRenamedClass");
-        MethodDeclaration setter = cu
-                .getClassByName("MyRenamedClass").get()
-                .addMethod("setAField", Modifier.PUBLIC);
-        setter.addParameter("boolean", "aField");
-        setter.getBody().get().getStatements().add(new ExpressionStmt(
-                new AssignExpr(
-                        new FieldAccessExpr(new ThisExpr(),"aField"),
-                        new NameExpr("aField"),
-                        AssignExpr.Operator.ASSIGN
-                )));
-        assertEquals(readExample("ASimpleClassWithMoreFormatting_step4"), LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void addingStatementToAnAddedMethodInASimpleClassWithMoreFormattingFromStep3() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting_step3");
-
-        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
-                .getMethodsByName("setAField").get(0);
-        setter.getBody().get().getStatements().add(new ExpressionStmt(
-                new AssignExpr(
-                        new FieldAccessExpr(new ThisExpr(),"aField"),
-                        new NameExpr("aField"),
-                        AssignExpr.Operator.ASSIGN
-                )));
-        assertEquals(readExample("ASimpleClassWithMoreFormatting_step4"), LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void nodeTextForMethod() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting_step4");
-
-        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
-                .getMethodsByName("setAField").get(0);
-        NodeText nodeText;
-
-        nodeText = getTextForNode(setter);
-        int index = 0;
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.PUBLIC));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(VoidType.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(SimpleName.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LPAREN));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(Parameter.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RPAREN));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(BlockStmt.class));
-        assertEquals(index, nodeText.getElements().size());
-
-        nodeText = getTextForNode(setter.getBody().get());
-        index = 0;
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LBRACE));
-        assertTrue(nodeText.getElements().get(index++).isNewline());
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(ExpressionStmt.class));
-        assertTrue(nodeText.getElements().get(index++).isNewline());
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RBRACE));
-        assertEquals(index, nodeText.getElements().size());
-
-        nodeText = getTextForNode(setter.getBody().get().getStatement(0));
-        index = 0;
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(AssignExpr.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SEMICOLON));
-        assertEquals(index, nodeText.getElements().size());
-    }
-
-    @Test
-    public void nodeTextForModifiedMethod() throws IOException {
-        considerExample("ASimpleClassWithMoreFormatting_step3");
-
-        MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
-                .getMethodsByName("setAField").get(0);
-        setter.getBody().get().getStatements().add(new ExpressionStmt(
-                new AssignExpr(
-                        new FieldAccessExpr(new ThisExpr(),"aField"),
-                        new NameExpr("aField"),
-                        AssignExpr.Operator.ASSIGN
-                )));
-        NodeText nodeText;
-
-        nodeText = getTextForNode(setter);
-        int index = 0;
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.PUBLIC));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(VoidType.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(SimpleName.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LPAREN));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(Parameter.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RPAREN));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(BlockStmt.class));
-        assertEquals(index, nodeText.getElements().size());
-
-        nodeText = getTextForNode(setter.getBody().get());
-        index = 0;
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.LBRACE));
-        assertTrue(nodeText.getElements().get(index++).isNewline());
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(ExpressionStmt.class));
-        assertTrue(nodeText.getElements().get(index++).isNewline());
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SPACE));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.RBRACE));
-        assertEquals(index, nodeText.getElements().size());
-
-        nodeText = LexicalPreservingPrinter.getOrCreateNodeText(setter.getBody().get().getStatement(0));
-        index = 0;
-        assertTrue(nodeText.getElements().get(index++).isChildOfClass(AssignExpr.class));
-        assertTrue(nodeText.getElements().get(index++).isToken(GeneratedJavaParserConstants.SEMICOLON));
-        assertEquals(index, nodeText.getElements().size());
-    }
-
-    // See issue #926
-    @Test
-    public void addASecondStatementToExistingMethod() throws IOException {
-        considerExample("MethodWithOneStatement");
-
-        MethodDeclaration methodDeclaration = cu.getType(0).getMethodsByName("someMethod").get(0);
-        methodDeclaration.getBody().get().getStatements().add(new ExpressionStmt(
-                new VariableDeclarationExpr(
-                        new VariableDeclarator(
-                                JavaParser.parseClassOrInterfaceType("String"),
-                                "test2",
-                                new StringLiteralExpr("")))
-        ));
-        assertEquals("public void someMethod() {" + EOL
-                + "        String test = \"\";" + EOL
-                + "        String test2 = \"\";" + EOL
-                + "    }", LexicalPreservingPrinter.print(methodDeclaration));
-    }
-
-    // See issue #866
-    @Test
-    public void moveOverrideAnnotations() {
-        String code = "public class TestPage extends Page {" + EOL +
-                EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   protected @Override void initializePage() {}" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes()
-                .forEach(type -> {
-                    type.getMembers()
-                            .forEach(member -> {
-                                member.ifMethodDeclaration(methodDeclaration -> {
-                                    if (methodDeclaration.getAnnotationByName("Override").isPresent()) {
-
-                                        while (methodDeclaration.getAnnotations().isNonEmpty()) {
-                                            AnnotationExpr annotationExpr = methodDeclaration.getAnnotations().get(0);
-                                            annotationExpr.remove();
-                                        }
-
-                                        methodDeclaration.addMarkerAnnotation("Override");
-                                    }
-                                });
-                            });
-                });
-        assertEquals("public class TestPage extends Page {" + EOL +
-                EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}", LexicalPreservingPrinter.print(cu));
-    }
-
-    // See issue #866
-    @Test
-    public void moveOrAddOverrideAnnotations() {
-        String code = "public class TestPage extends Page {" + EOL +
-                EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   protected @Override void initializePage() {}" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes()
-                .forEach(type -> {
-                    type.getMembers()
-                            .forEach(member -> {
-                                if (member instanceof MethodDeclaration) {
-                                    MethodDeclaration methodDeclaration = (MethodDeclaration) member;
-                                    if (methodDeclaration.getAnnotationByName("Override").isPresent()) {
-
-                                        while (methodDeclaration.getAnnotations().isNonEmpty()) {
-                                            AnnotationExpr annotationExpr = methodDeclaration.getAnnotations().get(0);
-                                            annotationExpr.remove();
-                                        }
-                                    }
-                                    methodDeclaration.addMarkerAnnotation("Override");
-                                }
-                            });
-                });
-        assertEquals("public class TestPage extends Page {" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}", LexicalPreservingPrinter.print(cu));
-    }
-
-    // See issue #865
-    @Test
-    public void handleAddingMarkerAnnotation() {
-        String code = "public class TestPage extends Page {" + EOL +
-                EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes()
-                .forEach(type -> {
-                    type.getMembers()
-                            .forEach(member -> {
-                                if (member instanceof MethodDeclaration) {
-                                    MethodDeclaration methodDeclaration = (MethodDeclaration) member;
-                                    if (!methodDeclaration.getAnnotationByName("Override").isPresent()) {
-                                        methodDeclaration.addMarkerAnnotation("Override");
-                                    }
-                                }
-                            });
-                });
-        assertEquals("public class TestPage extends Page {" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}", LexicalPreservingPrinter.print(cu));
-    }
-
-    // See issue #865
-    @Test
-    public void handleOverrideMarkerAnnotation() {
-        String code = "public class TestPage extends Page {" + EOL +
-                EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes()
-                .forEach(type -> type.getMembers()
-                        .forEach(member ->
-                            member.ifMethodDeclaration(methodDeclaration -> methodDeclaration.addMarkerAnnotation("Override")
-                        )));
-        assertEquals("public class TestPage extends Page {" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}", LexicalPreservingPrinter.print(cu));
-    }
-
-    // See issue #865
-    @Test
-    public void handleOverrideAnnotationAlternative() {
-        String code = "public class TestPage extends Page {" + EOL +
-                EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes()
-                .forEach(type -> type.getMembers()
-                        .forEach(member ->  member.ifMethodDeclaration(methodDeclaration -> methodDeclaration.addAnnotation("Override"))));
-        assertEquals("public class TestPage extends Page {" + EOL +
-                EOL +
-                "   @Override()" + EOL +
-                "   protected void test() {}" + EOL +
-                EOL +
-                "   @Override()" + EOL +
-                "   protected void initializePage() {}" + EOL +
-                "}", LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void invokeModifierVisitor() {
-        String code = "class A {" + EOL
-                + "  Object f() {" + EOL
-                + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
-                + "}}";
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-        cu.accept(new ModifierVisitor<>(), null);
-    }
-
-    @Test
-    public void handleDeprecatedAnnotationFinalClass() {
-        String code = "public final class A {}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes().forEach(type -> type.addAndGetAnnotation(Deprecated.class));
-
-        assertEquals("@Deprecated()" + EOL +
-                "public final class A {}" , LexicalPreservingPrinter.print(cu));
-
-    }
-
-    @Test
-    public void handleDeprecatedAnnotationAbstractClass() {
-        String code = "public abstract class A {}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-
-        cu.getTypes().forEach(type -> type.addAndGetAnnotation(Deprecated.class));
-
-        assertEquals("@Deprecated()" + EOL +
-                "public abstract class A {}" , LexicalPreservingPrinter.print(cu));
-    }
-
-    @Test
-    public void issue1244() {
-        String code = "public class Foo {" + EOL + EOL
-                + "// Some comment" + EOL + EOL // does work with only one \n
-                + "public void writeExternal() {}" + EOL + "}";
-        CompilationUnit originalCu = JavaParser.parse(code);
-        CompilationUnit cu = LexicalPreservingPrinter.setup(originalCu);
-
-        cu.findAll(ClassOrInterfaceDeclaration.class).stream().forEach(c -> {
-            List<MethodDeclaration> methods = c.getMethodsByName("writeExternal");
-            for (MethodDeclaration method : methods) {
-                c.remove(method);
-            }
-        });
-        assertEqualsNoEol("public class Foo {\n" +
-                "// Some comment\n\n" +
-                "}", LexicalPreservingPrinter.print(cu));
-    }
-
-    static class AddFooCallModifierVisitor extends ModifierVisitor<Void> {
-        @Override
-        public Visitable visit(MethodCallExpr n, Void arg) {
-            // Add a call to foo() on every found method call
-            return new MethodCallExpr(n, "foo");
-        }
-    }
-
-    // See issue 1277
-    @Test
-    public void testInvokeModifierVisitor() throws IOException {
-        String code = "class A {" + EOL +
-                "  public String message = \"hello\";" + EOL +
-                "   void bar() {" + EOL +
-                "     System.out.println(\"hello\");" + EOL +
-                "   }" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-        cu.accept(new AddFooCallModifierVisitor(), null);
-    }
-
-    static class CallModifierVisitor extends ModifierVisitor<Void> {
-        @Override
-        public Visitable visit(MethodCallExpr n, Void arg) {
-            // Add a call to foo() on every found method call
-            return new MethodCallExpr(n.clone(), "foo");
-        }
-    }
-
-    @Test
-    public void invokeModifierVisitorIssue1297() {
-        String code = "class A {" + EOL +
-                "   public void bar() {" + EOL +
-                "     System.out.println(\"hello\");" + EOL +
-                "     System.out.println(\"hello\");" + EOL +
-                "     // comment" + EOL +
-                "   }" + EOL +
-                "}";
-
-        CompilationUnit cu = JavaParser.parse(code);
-        LexicalPreservingPrinter.setup(cu);
-        cu.accept(new CallModifierVisitor(), null);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/TransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/TransformationsTest.java
deleted file mode 100644
index ec89dd1..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/TransformationsTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package com.github.javaparser.printer.lexicalpreservation;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.NullLiteralExpr;
-import com.github.javaparser.ast.stmt.ReturnStmt;
-import com.github.javaparser.ast.type.ArrayType;
-import com.github.javaparser.ast.type.PrimitiveType;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-/**
- * These tests are more "high level" than the ones in LexicalPreservingPrinterTest.
- * The idea is to perform some transformations on the code, print it back and see if the generated code
- * is the expected one. We do not care about the internal state of LexicalPreservingPrinter, just the visible result.
- */
-public class TransformationsTest extends  AbstractLexicalPreservingTest {
-
-    @Test
-    public void unchangedSimpleClasses() throws IOException {
-        assertUnchanged("Example1");
-        assertUnchanged("Example2");
-    }
-
-    @Test
-    public void unchangedComplexFile() throws IOException {
-        assertUnchanged("Example4");
-    }
-
-    @Test
-    public void example1() throws IOException {
-        considerExample("Example1_original");
-        cu.getClassByName("A").get().getFieldByName("a").get().setModifiers(EnumSet.of(Modifier.STATIC));
-        assertTransformed("Example1", cu);
-    }
-
-    @Test
-    public void example2() throws IOException {
-        considerExample("Example2_original");
-        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setInitializer("10");
-        assertTransformed("Example2", cu);
-    }
-
-    @Test
-    public void example3() throws IOException {
-        considerExample("Example3_original");
-        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setInitializer((Expression) null);
-        assertTransformed("Example3", cu);
-    }
-
-    @Test
-    public void example5() throws IOException {
-        considerExample("Example5_original");
-        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setInitializer(new NullLiteralExpr());
-        assertTransformed("Example5", cu);
-    }
-
-    @Test
-    public void example6() throws IOException {
-        considerExample("Example6_original");
-        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setName("someOtherName");
-        assertTransformed("Example6", cu);
-    }
-
-    @Test
-    public void example7() throws IOException {
-        considerExample("Example7_original");
-        cu.getClassByName("A").get().getFieldByName("a").get().getVariable(0).setType(new ArrayType(PrimitiveType.intType()));
-        assertTransformed("Example7", cu);
-    }
-
-    @Test
-    public void example8() throws IOException {
-        considerExample("Example8_original");
-        FieldDeclaration fd = (FieldDeclaration) cu.getClassByName("A").get().getMember(0).asFieldDeclaration();
-        fd.addVariable(new VariableDeclarator(PrimitiveType.intType(), "b"));
-        assertTransformed("Example8", cu);
-    }
-
-    @Test
-    public void example9() throws IOException {
-        considerExample("Example9_original");
-        FieldDeclaration fd = (FieldDeclaration) cu.getClassByName("A").get().getMember(0).asFieldDeclaration();
-        fd.addVariable(new VariableDeclarator(new ArrayType(PrimitiveType.intType()), "b"));
-        assertTransformed("Example9", cu);
-    }
-
-    @Test
-    public void example10() throws IOException {
-        considerExample("Example10_original");
-        cu.getClassByName("A").get().getMembers().remove(0);
-        assertTransformed("Example10", cu);
-    }
-
-    @Test
-    public void exampleParam1() throws IOException {
-        considerExample("Example_param1_original");
-        MethodDeclaration md = (MethodDeclaration) cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        md.addParameter("int", "p1");
-        assertTransformed("Example_param1", cu);
-    }
-
-    @Test
-    public void exampleParam2() throws IOException {
-        considerExample("Example_param1_original");
-        MethodDeclaration md = (MethodDeclaration) cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        md.addParameter(new ArrayType(PrimitiveType.intType()), "p1");
-        md.addParameter("char", "p2");
-        assertTransformed("Example_param2", cu);
-    }
-
-    @Test
-    public void exampleParam3() throws IOException {
-        considerExample("Example_param3_original");
-        MethodDeclaration md = (MethodDeclaration) cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        md.getParameters().remove(0);
-        assertTransformed("Example_param3", cu);
-    }
-
-    @Test
-    public void exampleParam4() throws IOException {
-        considerExample("Example_param3_original");
-        MethodDeclaration md = (MethodDeclaration) cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        md.getParameters().remove(1);
-        assertTransformed("Example_param4", cu);
-    }
-
-    @Test
-    public void exampleParam5() throws IOException {
-        considerExample("Example_param3_original");
-        MethodDeclaration md = (MethodDeclaration) cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
-        md.setType(PrimitiveType.intType());
-        assertTransformed("Example_param5b", cu);
-        md.getBody().get().getStatements().add(new ReturnStmt(new NameExpr("p1")));
-        assertTransformed("Example_param5", cu);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/ArrayCreationLevelTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/ArrayCreationLevelTransformationsTest.java
deleted file mode 100644
index 93cff34..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/ArrayCreationLevelTransformationsTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast;
-
-import com.github.javaparser.ast.ArrayCreationLevel;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.expr.ArrayCreationExpr;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.expr.NormalAnnotationExpr;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import com.github.javaparser.utils.Utils;
-import org.junit.Test;
-
-import java.io.IOException;
-
-/**
- * Transforming ArrayCreationLevel and verifying the LexicalPreservation works as expected.
- */
-public class ArrayCreationLevelTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected ArrayCreationLevel consider(String code) {
-        considerExpression("new int" + code);
-        ArrayCreationExpr arrayCreationExpr = expression.asArrayCreationExpr();
-        return arrayCreationExpr.getLevels().get(0);
-    }
-
-    // Dimension
-
-    @Test
-    public void addingDimension() throws IOException {
-        ArrayCreationLevel it = consider("[]");
-        it.setDimension(new IntegerLiteralExpr("10"));
-        assertTransformedToString("[10]", it);
-    }
-
-    @Test
-    public void removingDimension() throws IOException {
-        ArrayCreationLevel it = consider("[10]");
-        it.removeDimension();
-        assertTransformedToString("[]", it);
-    }
-
-    @Test
-    public void replacingDimension() throws IOException {
-        ArrayCreationLevel it = consider("[10]");
-        it.setDimension(new IntegerLiteralExpr("12"));
-        assertTransformedToString("[12]", it);
-    }
-
-    // Annotations
-
-    @Test
-    public void addingAnnotation() throws IOException {
-        ArrayCreationLevel it = consider("[]");
-        it.addAnnotation("myAnno");
-        assertTransformedToString("@myAnno()"+ Utils.EOL+"[]", it);
-    }
-
-    @Test
-    public void removingAnnotation() throws IOException {
-        ArrayCreationLevel it = consider("@myAnno []");
-        it.getAnnotations().remove(0);
-        assertTransformedToString("[]", it);
-    }
-
-    @Test
-    public void replacingAnnotation() throws IOException {
-        ArrayCreationLevel it = consider("@myAnno []");
-        it.getAnnotations().set(0, new NormalAnnotationExpr(new Name("myOtherAnno"), new NodeList<>()));
-        assertTransformedToString("@myOtherAnno() []", it);
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/CompilationUnitTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/CompilationUnitTransformationsTest.java
deleted file mode 100644
index 3040378..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/CompilationUnitTransformationsTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast;
-
-import com.github.javaparser.ast.PackageDeclaration;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-
-import static com.github.javaparser.utils.Utils.EOL;
-
-/**
- * Transforming CompilationUnit and verifying the LexicalPreservation works as expected.
- */
-public class CompilationUnitTransformationsTest extends AbstractLexicalPreservingTest {
-
-    // packageDeclaration
-
-    @Test
-    public void addingPackageDeclaration() throws IOException {
-        considerCode("class A {}");
-        cu.setPackageDeclaration(new PackageDeclaration(new Name(new Name("foo"), "bar")));
-        assertTransformedToString("package foo.bar;"+ EOL + EOL + "class A {}", cu);
-    }
-
-    @Test
-    public void removingPackageDeclaration() throws IOException {
-        considerCode("package foo.bar; class A {}");
-        cu.removePackageDeclaration();
-        assertTransformedToString("class A {}", cu);
-    }
-
-    @Test
-    public void replacingPackageDeclaration() throws IOException {
-        considerCode("package foo.bar; class A {}");
-        cu.setPackageDeclaration(new PackageDeclaration(new Name(new Name("foo2"), "baz")));
-        assertTransformedToString("package foo2.baz;" +
-                EOL + EOL +
-                " class A {}", cu);
-    }
-
-    // imports
-
-    // types
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationDeclarationTransformationsTest.java
deleted file mode 100644
index a2ffd40..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
-import com.github.javaparser.ast.type.PrimitiveType;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Transforming AnnotationDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class AnnotationDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    @Test
-    public void unchangedExamples() throws IOException {
-        assertUnchanged("AnnotationDeclaration_Example1");
-        assertUnchanged("AnnotationDeclaration_Example3");
-        assertUnchanged("AnnotationDeclaration_Example9");
-    }
-
-    // name
-
-    @Test
-    public void changingName() throws IOException {
-        considerExample("AnnotationDeclaration_Example1_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().setName("NewName");
-        assertTransformed("AnnotationDeclaration_Example1", cu);
-    }
-
-    // modifiers
-
-    @Test
-    public void addingModifiers() throws IOException {
-        considerExample("AnnotationDeclaration_Example1_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().setModifiers(EnumSet.of(Modifier.PUBLIC));
-        assertTransformed("AnnotationDeclaration_Example2", cu);
-    }
-
-    @Test
-    public void removingModifiers() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().setModifiers(EnumSet.noneOf(Modifier.class));
-        assertTransformed("AnnotationDeclaration_Example3", cu);
-    }
-
-    @Test
-    public void replacingModifiers() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().setModifiers(EnumSet.of(Modifier.PROTECTED));
-        assertTransformed("AnnotationDeclaration_Example4", cu);
-    }
-
-    // members
-
-    @Test
-    public void addingMember() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().addMember(new AnnotationMemberDeclaration(EnumSet.noneOf(Modifier.class), PrimitiveType.intType(), "foo", null));
-        assertTransformed("AnnotationDeclaration_Example5", cu);
-    }
-
-    @Test
-    public void removingMember() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().getMember(2).remove();
-        assertTransformed("AnnotationDeclaration_Example6", cu);
-    }
-
-    @Test
-    public void replacingMember() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().setMember(2, new AnnotationMemberDeclaration(EnumSet.noneOf(Modifier.class), PrimitiveType.intType(), "foo", null));
-        assertTransformed("AnnotationDeclaration_Example7", cu);
-    }
-
-    // javadoc
-
-    @Test
-    public void addingJavadoc() throws IOException {
-        considerExample("AnnotationDeclaration_Example3_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().setJavadocComment("Cool this annotation!");
-        assertTransformed("AnnotationDeclaration_Example8", cu);
-    }
-
-    @Test
-    public void removingJavadoc() throws IOException {
-        considerExample("AnnotationDeclaration_Example9_original");
-        boolean removed = cu.getAnnotationDeclarationByName("ClassPreamble").get().getJavadocComment().get().remove();
-        assertEquals(true, removed);
-        assertTransformed("AnnotationDeclaration_Example9", cu);
-    }
-
-    @Test
-    public void replacingJavadoc() throws IOException {
-        considerExample("AnnotationDeclaration_Example9_original");
-        cu.getAnnotationDeclarationByName("ClassPreamble").get().setJavadocComment("Super extra cool this annotation!!!");
-        assertTransformed("AnnotationDeclaration_Example10", cu);
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationMemberDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationMemberDeclarationTransformationsTest.java
deleted file mode 100644
index 6b55528..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/AnnotationMemberDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.expr.Name;
-import com.github.javaparser.ast.expr.NormalAnnotationExpr;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.util.EnumSet;
-
-import static com.github.javaparser.utils.Utils.EOL;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Transforming AnnotationMemberDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class AnnotationMemberDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected AnnotationMemberDeclaration consider(String code) {
-        considerCode("@interface AD { " + code + " }");
-        return cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
-    }
-
-    // Name
-
-    @Test
-    public void changingName() {
-        AnnotationMemberDeclaration md = consider("int foo();");
-        md.setName("bar");
-        assertTransformedToString("int bar();", md);
-    }
-
-    // Type
-
-    @Test
-    public void changingType() {
-        AnnotationMemberDeclaration md = consider("int foo();");
-        md.setType("String");
-        assertTransformedToString("String foo();", md);
-    }
-
-    // Modifiers
-
-    @Test
-    public void addingModifiers() {
-        AnnotationMemberDeclaration md = consider("int foo();");
-        md.setModifiers(EnumSet.of(Modifier.PUBLIC));
-        assertTransformedToString("public int foo();", md);
-    }
-
-    @Test
-    public void removingModifiers() {
-        AnnotationMemberDeclaration md = consider("public int foo();");
-        md.setModifiers(EnumSet.noneOf(Modifier.class));
-        assertTransformedToString("int foo();", md);
-    }
-
-    @Test
-    public void replacingModifiers() {
-        AnnotationMemberDeclaration md = consider("public int foo();");
-        md.setModifiers(EnumSet.of(Modifier.PROTECTED));
-        assertTransformedToString("protected int foo();", md);
-    }
-
-    // Default value
-
-    @Test
-    public void addingDefaultValue() {
-        AnnotationMemberDeclaration md = consider("int foo();");
-        md.setDefaultValue(new IntegerLiteralExpr("10"));
-        assertTransformedToString("int foo() default 10;", md);
-    }
-
-    @Test
-    public void removingDefaultValue() {
-        AnnotationMemberDeclaration md = consider("int foo() default 10;");
-        assertEquals(true, md.getDefaultValue().get().remove());
-        assertTransformedToString("int foo();", md);
-    }
-
-    @Test
-    public void replacingDefaultValue() {
-        AnnotationMemberDeclaration md = consider("int foo() default 10;");
-        md.setDefaultValue(new IntegerLiteralExpr("11"));
-        assertTransformedToString("int foo() default 11;", md);
-    }
-
-    // Annotations
-
-    @Test
-    public void addingAnnotation() {
-        AnnotationMemberDeclaration it = consider("int foo();");
-        it.addAnnotation("myAnno");
-        assertTransformedToString("@myAnno()" + EOL + "int foo();", it);
-    }
-
-    @Test
-    public void addingTwoAnnotations() {
-        AnnotationMemberDeclaration it = consider("int foo();");
-        it.addAnnotation("myAnno");
-        it.addAnnotation("myAnno2");
-        assertTransformedToString("@myAnno()" + EOL + "@myAnno2()" + EOL + "int foo();", it);
-    }
-
-    @Test
-    public void removingAnnotationOnSomeLine() {
-        AnnotationMemberDeclaration it = consider("@myAnno int foo();");
-        it.getAnnotations().remove(0);
-        assertTransformedToString("int foo();", it);
-    }
-
-    @Test
-    public void removingAnnotationOnPrevLine() {
-        AnnotationMemberDeclaration it = consider("@myAnno" + EOL + "int foo();");
-        it.getAnnotations().remove(0);
-        assertTransformedToString("int foo();", it);
-    }
-
-    @Test
-    public void replacingAnnotation() {
-        AnnotationMemberDeclaration it = consider("@myAnno int foo();");
-        it.getAnnotations().set(0, new NormalAnnotationExpr(new Name("myOtherAnno"), new NodeList<>()));
-        assertTransformedToString("@myOtherAnno() int foo();", it);
-    }
-
-    // Javadoc
-
-    @Test
-    public void addingJavadoc() {
-        AnnotationMemberDeclaration it = consider("int foo();");
-        it.setJavadocComment("Cool this annotation!");
-        assertTransformedToString("@interface AD { /** Cool this annotation!*/" + EOL +
-                "int foo(); }", it.getParentNode().get());
-    }
-
-    @Test
-    public void removingJavadoc() {
-        AnnotationMemberDeclaration it = consider("/** Cool this annotation!*/ int foo();");
-        assertTrue(it.getJavadocComment().get().remove());
-        assertTransformedToString("@interface AD {  int foo(); }", it.getParentNode().get());
-    }
-
-    @Test
-    public void replacingJavadoc() {
-        AnnotationMemberDeclaration it = consider("/** Cool this annotation!*/ int foo();");
-        it.setJavadocComment("Super extra cool this annotation!!!");
-        assertTransformedToString("@interface AD { /** Super extra cool this annotation!!!*/ int foo(); }", it.getParentNode().get());
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ClassOrInterfaceDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ClassOrInterfaceDeclarationTransformationsTest.java
deleted file mode 100644
index 1be8037..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ClassOrInterfaceDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.type.PrimitiveType;
-import com.github.javaparser.ast.type.TypeParameter;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
-import static com.github.javaparser.utils.Utils.EOL;
-
-/**
- * Transforming ClassOrInterfaceDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class ClassOrInterfaceDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected ClassOrInterfaceDeclaration consider(String code) {
-        considerCode(code);
-        return cu.getType(0).asClassOrInterfaceDeclaration();
-    }
-
-    // Name
-
-    @Test
-    public void settingName() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A {}");
-        cid.setName("B");
-        assertTransformedToString("class B {}", cid);
-    }
-
-    // isInterface
-
-    @Test
-    public void classToInterface() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A {}");
-        cid.setInterface(true);
-        assertTransformedToString("interface A {}", cid);
-    }
-
-    @Test
-    public void interfaceToClass() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("interface A {}");
-        cid.setInterface(false);
-        assertTransformedToString("class A {}", cid);
-    }
-
-    // typeParameters
-
-    @Test
-    public void addingTypeParameterWhenThereAreNone() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A {}");
-        cid.addTypeParameter(new TypeParameter("T", new NodeList<>()));
-        assertTransformedToString("class A<T> {}", cid);
-    }
-
-    @Test
-    public void addingTypeParameterAsFirstWhenThereAreSome() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A<U> {}");
-        cid.getTypeParameters().addFirst(new TypeParameter("T", new NodeList<>()));
-        assertTransformedToString("class A<T, U> {}", cid);
-    }
-
-    @Test
-    public void addingTypeParameterAsLastWhenThereAreSome() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A<U> {}");
-        cid.addTypeParameter(new TypeParameter("T", new NodeList<>()));
-        assertTransformedToString("class A<U, T> {}", cid);
-    }
-
-    // extendedTypes
-
-    @Test
-    public void addingExtendedTypes() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A {}");
-        cid.addExtendedType("Foo");
-        assertTransformedToString("class A extends Foo {}", cid);
-    }
-
-    @Test
-    public void removingExtendedTypes() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A extends Foo {}");
-        cid.getExtendedTypes().remove(0);
-        assertTransformedToString("public class A {}", cid);
-    }
-
-    @Test
-    public void replacingExtendedTypes() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A extends Foo {}");
-        cid.getExtendedTypes().set(0, parseClassOrInterfaceType("Bar"));
-        assertTransformedToString("public class A extends Bar {}", cid);
-    }
-
-    // implementedTypes
-
-    @Test
-    public void addingImplementedTypes() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A {}");
-        cid.addImplementedType("Foo");
-        assertTransformedToString("class A implements Foo {}", cid);
-    }
-
-    @Test
-    public void removingImplementedTypes() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A implements Foo {}");
-        cid.getImplementedTypes().remove(0);
-        assertTransformedToString("public class A {}", cid);
-    }
-
-    @Test
-    public void replacingImplementedTypes() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A implements Foo {}");
-        cid.getImplementedTypes().set(0, parseClassOrInterfaceType("Bar"));
-        assertTransformedToString("public class A implements Bar {}", cid);
-    }
-
-    // Modifiers
-
-    @Test
-    public void addingModifiers() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A {}");
-        cid.setModifiers(EnumSet.of(Modifier.PUBLIC));
-        assertTransformedToString("public class A {}", cid);
-    }
-
-    @Test
-    public void removingModifiers() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A {}");
-        cid.setModifiers(EnumSet.noneOf(Modifier.class));
-        assertTransformedToString("class A {}", cid);
-    }
-
-    @Test
-    public void replacingModifiers() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A {}");
-        cid.setModifiers(EnumSet.of(Modifier.PROTECTED));
-        assertTransformedToString("protected class A {}", cid);
-    }
-
-    // members
-
-    @Test
-    public void addingField() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("class A {}");
-        cid.addField("int", "foo");
-        assertTransformedToString("class A {" + EOL + "    int foo;" + EOL + "}", cid);
-    }
-
-    @Test
-    public void removingField() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A { int foo; }");
-        cid.getMembers().remove(0);
-        assertTransformedToString("public class A {}", cid);
-    }
-
-    @Test
-    public void replacingFieldWithAnotherField() throws IOException {
-        ClassOrInterfaceDeclaration cid = consider("public class A {float f;}");
-        cid.getMembers().set(0, new FieldDeclaration(EnumSet.noneOf(Modifier.class), new VariableDeclarator(PrimitiveType.intType(), "bar")));
-        assertTransformedToString("public class A {int bar;}", cid);
-    }
-
-    // Annotations
-
-    // Javadoc
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ConstructorDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ConstructorDeclarationTransformationsTest.java
deleted file mode 100644
index 6889a70..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/ConstructorDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.ConstructorDeclaration;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.expr.SimpleName;
-import com.github.javaparser.ast.type.ArrayType;
-import com.github.javaparser.ast.type.PrimitiveType;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-/**
- * Transforming ConstructorDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class ConstructorDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected ConstructorDeclaration consider(String code) {
-        considerCode("class A { " + code + " }");
-        return cu.getType(0).getMembers().get(0).asConstructorDeclaration();
-    }
-
-    // Name
-
-    @Test
-    public void settingName() throws IOException {
-        ConstructorDeclaration cd = consider("A(){}");
-        cd.setName("B");
-        assertTransformedToString("B(){}", cd);
-    }
-
-    // JavaDoc
-
-    // Modifiers
-
-    @Test
-    public void addingModifiers() throws IOException {
-        ConstructorDeclaration cd = consider("A(){}");
-        cd.setModifiers(EnumSet.of(Modifier.PUBLIC));
-        assertTransformedToString("public A(){}", cd);
-    }
-
-    @Test
-    public void removingModifiers() throws IOException {
-        ConstructorDeclaration cd = consider("public A(){}");
-        cd.setModifiers(EnumSet.noneOf(Modifier.class));
-        assertTransformedToString("A(){}", cd);
-    }
-
-    @Test
-    public void replacingModifiers() throws IOException {
-        ConstructorDeclaration cd = consider("public A(){}");
-        cd.setModifiers(EnumSet.of(Modifier.PROTECTED));
-        assertTransformedToString("protected A(){}", cd);
-    }
-
-    // Parameters
-
-    @Test
-    public void addingParameters() throws IOException {
-        ConstructorDeclaration cd = consider("A(){}");
-        cd.addParameter(PrimitiveType.doubleType(), "d");
-        assertTransformedToString("A(double d){}", cd);
-    }
-
-    @Test
-    public void removingOnlyParameter() throws IOException {
-        ConstructorDeclaration cd = consider("public A(double d){}");
-        cd.getParameters().remove(0);
-        assertTransformedToString("public A(){}", cd);
-    }
-
-    @Test
-    public void removingFirstParameterOfMany() throws IOException {
-        ConstructorDeclaration cd = consider("public A(double d, float f){}");
-        cd.getParameters().remove(0);
-        assertTransformedToString("public A(float f){}", cd);
-    }
-
-    @Test
-    public void removingLastParameterOfMany() throws IOException {
-        ConstructorDeclaration cd = consider("public A(double d, float f){}");
-        cd.getParameters().remove(1);
-        assertTransformedToString("public A(double d){}", cd);
-    }
-
-    @Test
-    public void replacingOnlyParameter() throws IOException {
-        ConstructorDeclaration cd = consider("public A(float f){}");
-        cd.getParameters().set(0, new Parameter(new ArrayType(PrimitiveType.intType()), new SimpleName("foo")));
-        assertTransformedToString("public A(int[] foo){}", cd);
-    }
-
-    // ThrownExceptions
-
-    // Body
-
-    // Annotations
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumConstantDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumConstantDeclarationTransformationsTest.java
deleted file mode 100644
index dff71cc..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumConstantDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.body.EnumConstantDeclaration;
-import com.github.javaparser.ast.body.EnumDeclaration;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-
-/**
- * Transforming EnumConstantDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class EnumConstantDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected EnumConstantDeclaration consider(String code) {
-        considerCode("enum A { " + code + " }");
-        return cu.getType(0).asEnumDeclaration().getEntries().get(0);
-    }
-
-    // Name
-
-    @Test
-    public void settingName() throws IOException {
-        EnumConstantDeclaration ecd = consider("A");
-        ecd.setName("B");
-        assertTransformedToString("B", ecd);
-    }
-
-    // Annotations
-
-    // Javadoc
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumDeclarationTransformationsTest.java
deleted file mode 100644
index e2a8fa3..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/EnumDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.EnumDeclaration;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-/**
- * Transforming EnumDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class EnumDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected EnumDeclaration consider(String code) {
-        considerCode(code);
-        return cu.getType(0).asEnumDeclaration();
-    }
-
-    // Name
-
-    @Test
-    public void settingName() throws IOException {
-        EnumDeclaration cid = consider("enum A { E1, E2 }");
-        cid.setName("B");
-        assertTransformedToString("enum B { E1, E2 }", cid);
-    }
-
-    // implementedTypes
-
-    // Modifiers
-
-    @Test
-    public void addingModifiers() throws IOException {
-        EnumDeclaration ed = consider("enum A { E1, E2 }");
-        ed.setModifiers(EnumSet.of(Modifier.PUBLIC));
-        assertTransformedToString("public enum A { E1, E2 }", ed);
-    }
-
-    @Test
-    public void removingModifiers() throws IOException {
-        EnumDeclaration ed = consider("public enum A { E1, E2 }");
-        ed.setModifiers(EnumSet.noneOf(Modifier.class));
-        assertTransformedToString("enum A { E1, E2 }", ed);
-    }
-
-    @Test
-    public void replacingModifiers() throws IOException {
-        EnumDeclaration ed = consider("public enum A { E1, E2 }");
-        ed.setModifiers(EnumSet.of(Modifier.PROTECTED));
-        assertTransformedToString("protected enum A { E1, E2 }", ed);
-    }
-
-    // members
-
-    // Annotations
-
-    // Javadoc
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/FieldDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/FieldDeclarationTransformationsTest.java
deleted file mode 100644
index 994f5d8..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/FieldDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-/**
- * Transforming FieldDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class FieldDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected FieldDeclaration consider(String code) {
-        considerCode("class A { " + code + " }");
-        return cu.getType(0).getMembers().get(0).asFieldDeclaration();
-    }
-
-    // JavaDoc
-
-    // Modifiers
-
-    @Test
-    public void addingModifiers() {
-        FieldDeclaration it = consider("int A;");
-        it.setModifiers(EnumSet.of(Modifier.PUBLIC));
-        assertTransformedToString("public int A;", it);
-    }
-
-    @Test
-    public void removingModifiers() {
-        FieldDeclaration it = consider("public int A;");
-        it.setModifiers(EnumSet.noneOf(Modifier.class));
-        assertTransformedToString("int A;", it);
-    }
-
-    @Test
-    public void replacingModifiers() {
-        FieldDeclaration it = consider("int A;");
-        it.setModifiers(EnumSet.of(Modifier.PROTECTED));
-        assertTransformedToString("protected int A;", it);
-    }
-
-    @Test
-    public void changingTypes() {
-        FieldDeclaration it = consider("int a, b;");
-        assertTransformedToString("int a, b;", it);
-        it.getVariable(0).setType("Xyz");
-        assertTransformedToString(" a, b;", it);
-        it.getVariable(1).setType("Xyz");
-        assertTransformedToString("Xyz a, b;", it);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/InitializerDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/InitializerDeclarationTransformationsTest.java
deleted file mode 100644
index 738acb3..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/InitializerDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.body.InitializerDeclaration;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-
-/**
- * Transforming InitializerDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class InitializerDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected InitializerDeclaration consider(String code) {
-        considerCode("class A { " + code + " }");
-        return cu.getType(0).getMembers().get(0).asInitializerDeclaration();
-    }
-
-    // JavaDoc
-
-    // Body
-
-    // IsStatic
-
-    @Test
-    public void instanceToStatic() throws IOException {
-        InitializerDeclaration it = consider("{ /*some comment*/ }");
-        it.setStatic(true);
-        assertTransformedToString("static { /*some comment*/ }", it);
-    }
-
-    @Test
-    public void staticToInstance() throws IOException {
-        InitializerDeclaration it = consider("static { /*some comment*/ }");
-        it.setStatic(false);
-        assertTransformedToString("{ /*some comment*/ }", it);
-    }
-
-    // Annotations
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/MethodDeclarationTransformationsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/MethodDeclarationTransformationsTest.java
deleted file mode 100644
index 1f94f38..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/transformations/ast/body/MethodDeclarationTransformationsTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.printer.lexicalpreservation.transformations.ast.body;
-
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.expr.SimpleName;
-import com.github.javaparser.ast.type.ArrayType;
-import com.github.javaparser.ast.type.PrimitiveType;
-import com.github.javaparser.printer.lexicalpreservation.AbstractLexicalPreservingTest;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.EnumSet;
-
-/**
- * Transforming MethodDeclaration and verifying the LexicalPreservation works as expected.
- */
-public class MethodDeclarationTransformationsTest extends AbstractLexicalPreservingTest {
-
-    protected MethodDeclaration consider(String code) {
-        considerCode("class A { " + code + " }");
-        return cu.getType(0).getMembers().get(0).asMethodDeclaration();
-    }
-
-    // Name
-
-    @Test
-    public void settingName() throws IOException {
-        MethodDeclaration it = consider("void A(){}");
-        it.setName("B");
-        assertTransformedToString("void B(){}", it);
-    }
-
-    // JavaDoc
-
-    // Modifiers
-
-    @Test
-    public void addingModifiers() throws IOException {
-        MethodDeclaration it = consider("void A(){}");
-        it.setModifiers(EnumSet.of(Modifier.PUBLIC));
-        assertTransformedToString("public void A(){}", it);
-    }
-
-    @Test
-    public void removingModifiers() throws IOException {
-        MethodDeclaration it = consider("public void A(){}");
-        it.setModifiers(EnumSet.noneOf(Modifier.class));
-        assertTransformedToString("void A(){}", it);
-    }
-
-    @Test
-    public void replacingModifiers() throws IOException {
-        MethodDeclaration it = consider("public void A(){}");
-        it.setModifiers(EnumSet.of(Modifier.PROTECTED));
-        assertTransformedToString("protected void A(){}", it);
-    }
-
-    // Parameters
-
-    @Test
-    public void addingParameters() throws IOException {
-        MethodDeclaration it = consider("void foo(){}");
-        it.addParameter(PrimitiveType.doubleType(), "d");
-        assertTransformedToString("void foo(double d){}", it);
-    }
-
-    @Test
-    public void removingOnlyParameter() throws IOException {
-        MethodDeclaration it = consider("public void foo(double d){}");
-        it.getParameters().remove(0);
-        assertTransformedToString("public void foo(){}", it);
-    }
-
-    @Test
-    public void removingFirstParameterOfMany() throws IOException {
-        MethodDeclaration it = consider("public void foo(double d, float f){}");
-        it.getParameters().remove(0);
-        assertTransformedToString("public void foo(float f){}", it);
-    }
-
-    @Test
-    public void removingLastParameterOfMany() throws IOException {
-        MethodDeclaration it = consider("public void foo(double d, float f){}");
-        it.getParameters().remove(1);
-        assertTransformedToString("public void foo(double d){}", it);
-    }
-
-    @Test
-    public void replacingOnlyParameter() throws IOException {
-        MethodDeclaration it = consider("public void foo(float f){}");
-        it.getParameters().set(0, new Parameter(new ArrayType(PrimitiveType.intType()), new SimpleName("foo")));
-        assertTransformedToString("public void foo(int[] foo){}", it);
-    }
-
-    // ThrownExceptions
-
-    // Body
-
-    // Annotations
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/remove/NodeRemovalTest.java b/javaparser-testing/src/test/java/com/github/javaparser/remove/NodeRemovalTest.java
deleted file mode 100644
index 6620bb1..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/remove/NodeRemovalTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.remove;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.FieldDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.stmt.BlockStmt;
-import com.github.javaparser.ast.stmt.Statement;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class NodeRemovalTest {
-    private final CompilationUnit cu = new CompilationUnit();
-
-    @Test
-    public void testRemoveClassFromCompilationUnit() {
-        ClassOrInterfaceDeclaration testClass = cu.addClass("test");
-        assertEquals(1, cu.getTypes().size());
-        boolean remove = testClass.remove();
-        assertEquals(true, remove);
-        assertEquals(0, cu.getTypes().size());
-    }
-
-    @Test
-    public void testRemoveFieldFromClass() {
-        ClassOrInterfaceDeclaration testClass = cu.addClass("test");
-
-        FieldDeclaration addField = testClass.addField(String.class, "test");
-        assertEquals(1, testClass.getMembers().size());
-        boolean remove = addField.remove();
-        assertEquals(true, remove);
-        assertEquals(0, testClass.getMembers().size());
-    }
-
-    @Test
-    public void testRemoveStatementFromMethodBody() {
-        ClassOrInterfaceDeclaration testClass = cu.addClass("testC");
-
-        MethodDeclaration addMethod = testClass.addMethod("testM");
-        BlockStmt methodBody = addMethod.createBody();
-        Statement addStatement = methodBody.addAndGetStatement("test");
-        assertEquals(1, methodBody.getStatements().size());
-        boolean remove = addStatement.remove();
-        assertEquals(true, remove);
-        assertEquals(0, methodBody.getStatements().size());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/CodeGenerationUtilsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/CodeGenerationUtilsTest.java
deleted file mode 100644
index dafe7ad..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/CodeGenerationUtilsTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.github.javaparser.utils;
-
-import org.junit.Test;
-
-import static com.github.javaparser.utils.CodeGenerationUtils.*;
-import static org.junit.Assert.*;
-
-public class CodeGenerationUtilsTest {
-    @Test
-    public void setters() {
-        assertEquals("setValue", setterName("value"));
-        assertEquals("setBlue", setterName("isBlue"));
-    }
-
-    @Test
-    public void getters() {
-        assertEquals("getValue", getterName(Object.class, "value"));
-        assertEquals("isBlue", getterName(Boolean.class, "isBlue"));
-        assertEquals("isBlue", getterName(Boolean.class, "blue"));
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/PairTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/PairTest.java
deleted file mode 100644
index 2a5b84a..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/PairTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.github.javaparser.utils;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class PairTest {
-    @Test
-    public void testToString() {
-        Pair<String, String> pair = new Pair<>("abc", "def");
-
-        assertEquals("<abc, def>", pair.toString());
-    }
-
-    @Test
-    public void testToStringNulls() {
-        Pair<String, String> pair = new Pair<>(null, null);
-
-        assertEquals("<null, null>", pair.toString());
-    }
-}
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
deleted file mode 100644
index a0bb50e..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceRootTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.github.javaparser.utils;
-
-import com.github.javaparser.ParseResult;
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class SourceRootTest {
-    private final Path root = CodeGenerationUtils.classLoaderRoot(SourceRootTest.class).resolve("com/github/javaparser/utils/");
-    private final SourceRoot sourceRoot = new SourceRoot(root);
-
-    @Test
-    public void parseTestDirectory() throws IOException {
-
-        List<ParseResult<CompilationUnit>> parseResults = sourceRoot.tryToParse();
-        List<CompilationUnit> units = sourceRoot.getCompilationUnits();
-
-        assertEquals(2, units.size());
-        assertTrue(units.stream().allMatch(unit -> !unit.getTypes().isEmpty() || unit.getModule().isPresent()));
-        assertTrue(parseResults.stream().anyMatch(cu -> cu.getResult().get().getStorage().get().getPath().toString().contains("source" + File.separator + "root")));
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void fileAsRootIsNotAllowed() {
-        Path path = CodeGenerationUtils.classLoaderRoot(SourceRootTest.class).resolve("/com/github/javaparser/utils/Bla.java");
-        new SourceRoot(path);
-    }
-    
-    
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java
deleted file mode 100644
index 05e80ab..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/SourceZipTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*

- * 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.utils;

-

-import com.github.javaparser.ParseResult;

-import com.github.javaparser.ast.CompilationUnit;

-import org.junit.Test;

-

-import java.io.IOException;

-import java.net.URISyntaxException;

-import java.nio.file.Path;

-import java.nio.file.Paths;

-import java.util.ArrayList;

-import java.util.List;

-

-import static org.junit.Assert.assertEquals;

-import static org.junit.Assert.assertTrue;

-

-public class SourceZipTest {

-

-    private final Path testDir = CodeGenerationUtils.mavenModuleRoot(SourceZipTest.class)

-            .resolve(Paths.get("..", "javaparser-testing", "src", "test", "resources", "com", "github", "javaparser",

-                    "source_zip"))

-            .normalize();

-

-    @Test

-    public void parseTestDirectory() throws URISyntaxException, IOException {

-        SourceZip sourceZip = new SourceZip(testDir.resolve("test.zip"));

-        List<Pair<Path, ParseResult<CompilationUnit>>> results = sourceZip.parse();

-        assertEquals(3, results.size());

-        List<CompilationUnit> units = new ArrayList<>();

-        for (Pair<Path, ParseResult<CompilationUnit>> pr : results) {

-            units.add(pr.b.getResult().get());

-        }

-        assertTrue(units.stream().noneMatch(unit -> unit.getTypes().isEmpty()));

-    }

-

-    @Test

-    public void parseTestDirectoryWithCallback() throws URISyntaxException, IOException {

-        SourceZip sourceZip = new SourceZip(testDir.resolve("test.zip"));

-        List<Pair<Path, ParseResult<CompilationUnit>>> results = new ArrayList<>();

-

-        sourceZip.parse((path, result) -> results.add(new Pair<>(path, result)));

-

-        assertEquals(3, results.size());

-        List<CompilationUnit> units = new ArrayList<>();

-        for (Pair<Path, ParseResult<CompilationUnit>> pr : results) {

-            units.add(pr.b.getResult().get());

-        }

-        assertTrue(units.stream().noneMatch(unit -> unit.getTypes().isEmpty()));

-    }

-

-    @Test(expected = IOException.class)

-    public void dirAsZipIsNotAllowed() throws IOException {

-        new SourceZip(testDir.resolve("test")).parse();

-    }

-

-    @Test(expected = IOException.class)

-    public void fileAsZipIsNotAllowed() throws IOException {

-        new SourceZip(testDir.resolve("test.txt")).parse();

-    }

-}

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
deleted file mode 100644
index 24f1767..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/TestUtils.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package com.github.javaparser.utils;
-
-import com.github.javaparser.*;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.validator.Java9Validator;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-
-import java.io.*;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
-import static com.github.javaparser.Providers.provider;
-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;
-
-public class TestUtils {
-    /**
-     * Takes care of setting all the end of line character to platform specific ones.
-     */
-    public static String readResource(String resourceName) throws IOException {
-        if (resourceName.startsWith("/")) {
-            resourceName = resourceName.substring(1);
-        }
-        try (final InputStream resourceAsStream = TestUtils.class.getClassLoader().getResourceAsStream(resourceName)) {
-            if (resourceAsStream == null) {
-                fail("not found: " + resourceName);
-            }
-            try (final InputStreamReader reader = new InputStreamReader(resourceAsStream, "utf-8");
-                 final BufferedReader br = new BufferedReader(reader)) {
-                final StringBuilder builder = new StringBuilder();
-                String line;
-                while ((line = br.readLine()) != null) {
-                    builder.append(line).append(Utils.EOL);
-                }
-                return builder.toString();
-            }
-        }
-    }
-
-    public static void assertInstanceOf(Class<?> expectedType, Object instance) {
-        assertEquals(true, expectedType.isAssignableFrom(instance.getClass()), f("%s is not an instance of %s.", instance.getClass(), expectedType));
-    }
-
-    /**
-     * Unzip a zip file into a directory.
-     */
-    public static void unzip(Path zipFile, Path outputFolder) throws IOException {
-        Log.info("Unzipping %s to %s", zipFile, outputFolder);
-
-        final byte[] buffer = new byte[1024 * 1024];
-
-        outputFolder.toFile().mkdirs();
-
-        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile.toFile()))) {
-            ZipEntry ze = zis.getNextEntry();
-
-            while (ze != null) {
-                final Path newFile = outputFolder.resolve(ze.getName());
-
-                if (ze.isDirectory()) {
-                    Log.trace("mkdir %s", newFile.toAbsolutePath());
-                    newFile.toFile().mkdirs();
-                } else {
-                    Log.info("unzip %s", newFile.toAbsolutePath());
-                    try (FileOutputStream fos = new FileOutputStream(newFile.toFile())) {
-                        int len;
-                        while ((len = zis.read(buffer)) > 0) {
-                            fos.write(buffer, 0, len);
-                        }
-                    }
-                }
-                zis.closeEntry();
-                ze = zis.getNextEntry();
-            }
-
-        }
-        Log.info("Unzipped %s to %s", zipFile, outputFolder);
-    }
-
-    /**
-     * Download a file from a URL to disk.
-     */
-    public static void download(URL url, Path destination) throws IOException {
-        OkHttpClient client = new OkHttpClient();
-        Request request = new Request.Builder()
-                .url(url)
-                .build();
-
-        Response response = client.newCall(request).execute();
-        Files.write(destination, response.body().bytes());
-    }
-
-    public static String temporaryDirectory() {
-        return System.getProperty("java.io.tmpdir");
-    }
-
-    public static void assertCollections(Collection<?> expected, Collection<?> actual) {
-        final StringBuilder out = new StringBuilder();
-        for (Object e : expected) {
-            if (actual.contains(e)) {
-                actual.remove(e);
-            } else {
-                out.append("Missing: ").append(e).append(EOL);
-            }
-        }
-        for (Object a : actual) {
-            out.append("Unexpected: ").append(a).append(EOL);
-        }
-
-        String s = out.toString();
-        if (s.isEmpty()) {
-            return;
-        }
-        fail(s);
-    }
-
-    public static void assertProblems(ParseResult<?> result, String... expectedArg) {
-        assertProblems(result.getProblems(), expectedArg);
-    }
-
-    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<>(asList(expectedArg));
-        assertCollections(expected, actual);
-    }
-
-    public static void assertNoProblems(ParseResult<?> result) {
-        assertProblems(result);
-    }
-
-    public static void assertExpressionValid(String expression) {
-        JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9));
-        ParseResult<Expression> result = javaParser.parse(ParseStart.EXPRESSION, provider(expression));
-        assertEquals(true, result.isSuccessful(), result.getProblems().toString());
-    }
-
-    /**
-     * Assert that "actual" equals "expected", and that any EOL characters in "actual" are correct for the platform.
-     */
-    public static void assertEqualsNoEol(String expected, String actual) {
-        assertEquals(normalizeEolInTextBlock(expected, EOL), actual);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/UtilsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/UtilsTest.java
deleted file mode 100644
index 21ecf4c..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/UtilsTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.utils;
-
-import org.junit.Test;
-
-import static com.github.javaparser.utils.Utils.*;
-import static org.junit.Assert.assertEquals;
-
-public class UtilsTest {
-
-    @Test
-    public void testScreamingToCamelCase() {
-        assertEquals("abc", screamingToCamelCase("ABC"));
-        assertEquals("abcDef", screamingToCamelCase("ABC_DEF"));
-        assertEquals("abc", screamingToCamelCase("ABC_"));
-    }
-
-    @Test
-    public void screamingEmptyString() {
-        assertEquals("", camelCaseToScreaming(""));
-        assertEquals("ABC", camelCaseToScreaming("abc"));
-        assertEquals("HELLO_HELLO", camelCaseToScreaming("HelloHello"));
-        assertEquals("APE_TAIL", camelCaseToScreaming("apeTail"));
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void capitalizeOnEmptyString() {
-        capitalize("");
-    }
-
-    @Test
-    public void capitalizeOnStringOfOneCharacter() {
-        assertEquals("F", capitalize("f"));
-    }
-
-    @Test
-    public void capitalizeOnStringOfTwoCharacters() {
-        assertEquals("Fo", capitalize("fo"));
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void decapitalizeOnEmptyString() {
-        decapitalize("");
-    }
-
-    @Test
-    public void decapitalizeOnStringOfOneCharacter() {
-        assertEquals("f", decapitalize("F"));
-    }
-
-    @Test
-    public void decapitalizeOnStringOfTwoCharacters() {
-        assertEquals("fo", decapitalize("Fo"));
-    }
-    
-    @Test
-    public void normalizeEolInTextBlock() {
-        String result = Utils.normalizeEolInTextBlock("\r\n \r \n", "Q");
-        assertEquals("Q Q Q", result);
-    }
-
-    @Test
-    public void testTrimTrailingSpaces() {
-        assertEquals("abc", trimTrailingSpaces("abc"));
-        assertEquals("  abc", trimTrailingSpaces("  abc"));
-        assertEquals("abc", trimTrailingSpaces("abc  "));
-        assertEquals("  abc", trimTrailingSpaces("  abc  "));
-        assertEquals("abc", trimTrailingSpaces("abc\t\0"));
-        assertEquals("", trimTrailingSpaces("    "));
-        assertEquals("", trimTrailingSpaces(""));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorListTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorListTest.java
deleted file mode 100644
index c0944ec..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorListTest.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*

- * 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.utils;

-

-import static org.junit.Assert.assertEquals;

-import static org.junit.Assert.assertTrue;

-

-import java.util.ArrayList;

-import java.util.Iterator;

-import java.util.List;

-import java.util.Set;

-

-import org.junit.Test;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ast.CompilationUnit;

-import com.github.javaparser.ast.visitor.ObjectIdentityEqualsVisitor;

-import com.github.javaparser.ast.visitor.ObjectIdentityHashCodeVisitor;

-

-public class VisitorListTest {

-

-    @Test

-    public void visitorAddAll() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        vList.addAll(list);

-        for (int i = 0; i < list.size(); i++)

-            assertEquals(list.get(i), vList.get(i));

-    }

-

-    @Test

-    public void visitorAddAllAtIndex() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class Y{}"));

-        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        vList.add(JavaParser.parse("class A{}"));

-        vList.add(JavaParser.parse("class B{}"));

-        vList.addAll(2, list);

-        vList.add(JavaParser.parse("class C{}"));

-        for (int i = 0; i < list.size(); i++)

-            assertEquals(list.get(i), vList.get(2 + i));

-    }

-

-    @Test

-    public void visitorListContains() {

-        CompilationUnit x1 = JavaParser.parse("class X{}");

-        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        list.add(x1);

-        assertTrue(list.contains(x1));

-    }

-

-    @Test

-    public void visitorListContainsAll() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        vList.addAll(list);

-        assertTrue(vList.size() == 2 && vList.containsAll(list));

-    }

-

-    @Test

-    public void visitorListIterator() {

-        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        CompilationUnit x1 = JavaParser.parse("class X{}");

-        list.add(x1);

-        CompilationUnit x2 = JavaParser.parse("class X{}");

-        list.add(x2);

-        Iterator<CompilationUnit> itr = list.iterator();

-        assertEquals(x1, itr.next());

-        itr.remove();

-        assertTrue(list.size() == 1);

-        assertEquals(x2, itr.next());

-        itr.remove();

-        assertTrue(list.size() == 0);

-    }

-

-    @Test

-    public void visitorListListIterator() {

-        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        CompilationUnit x1 = JavaParser.parse("class X{}");

-        list.add(x1);

-        CompilationUnit x2 = JavaParser.parse("class X{}");

-        list.add(x2);

-        Iterator<CompilationUnit> itr = list.listIterator(2);

-        assertEquals(x1, itr.next());

-        itr.remove();

-        assertTrue(list.size() == 3);

-        assertEquals(x2, itr.next());

-        itr.remove();

-        assertTrue(list.size() == 2);

-    }

-

-    @Test

-    public void visitorListRemove() {

-        CompilationUnit x1 = JavaParser.parse("class X{}");

-        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        list.add(x1);

-        assertTrue(list.remove(x1));

-    }

-

-    @Test

-    public void visitorListRemoveAll() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        vList.addAll(list);

-        vList.removeAll(list);

-        assertTrue(vList.size() == 0);

-    }

-

-    @Test

-    public void visitorListRetainAll() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        VisitorList<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        vList.addAll(list);

-        vList.add(JavaParser.parse("class X{}"));

-        vList.retainAll(list);

-        assertTrue(vList.size() == 2);

-    }

-

-    @Test

-    public void visitorListSubList() {

-        VisitorList<CompilationUnit> list = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        assertTrue(list.size() == 4);

-        List<CompilationUnit> subLst = list.subList(1, 3);

-        assertTrue(subLst.size() == 2);

-        subLst.add(JavaParser.parse("class X{}"));

-        assertTrue(subLst.size() == 3);

-        assertTrue(list.size() == 5);

-

-    }

-

-    @Test

-    public void visitorListToArray() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        List<CompilationUnit> vList = new VisitorList<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        vList.addAll(list);

-        for (CompilationUnit u : vList.toArray(new CompilationUnit[2]))

-            assertTrue(vList.contains(u));

-    }

-

-}

diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorMapTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorMapTest.java
deleted file mode 100644
index 03d4b7b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorMapTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.github.javaparser.utils;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.visitor.ObjectIdentityEqualsVisitor;
-import com.github.javaparser.ast.visitor.ObjectIdentityHashCodeVisitor;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class VisitorMapTest {
-    @Test
-    public void normalEqualsDoesDeepCompare() {
-        CompilationUnit x1 = JavaParser.parse("class X{}");
-        CompilationUnit x2 = JavaParser.parse("class X{}");
-
-        Map<CompilationUnit, Integer> map = new HashMap<>();
-        map.put(x1, 1);
-        map.put(x2, 2);
-        assertEquals(1, map.size());
-    }
-
-    @Test
-    public void objectIdentityEqualsDoesShallowCompare() {
-        CompilationUnit x1 = JavaParser.parse("class X{}");
-        CompilationUnit x2 = JavaParser.parse("class X{}");
-
-        Map<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
-        map.put(x1, 1);
-        map.put(x2, 2);
-        assertEquals(2, map.size());
-    }
-    
-    @Test
-    public void visitorMapGet(){
-    	CompilationUnit x1 = JavaParser.parse("class X{}");
-
-        Map<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
-        map.put(x1, 1);
-        assertEquals(1, (int)map.get(x1));
-    }
-    
-    @Test
-    public void visitorMapContainsKey(){
-    	CompilationUnit x1 = JavaParser.parse("class X{}");
-
-        Map<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
-        map.put(x1, 1);
-        assertTrue(map.containsKey(x1));
-    }
-    
-    @Test
-    public void visitorMapPutAll(){
-    	CompilationUnit x1 = JavaParser.parse("class X{}");
-    	CompilationUnit x2 = JavaParser.parse("class Y{}");
-    	Map<CompilationUnit, Integer> map = new HashMap<>();
-    	map.put(x1, 1);
-    	map.put(x2, 2);
-    	Map<CompilationUnit, Integer> visitorMap = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
-        visitorMap.putAll(map);
-        assertEquals(2, visitorMap.size());
-    }
-    
-    @Test
-    public void remove(){
-        CompilationUnit x1 = JavaParser.parse("class X{}");
-        VisitorMap<CompilationUnit, Integer> map = new VisitorMap<>(new ObjectIdentityHashCodeVisitor(), new ObjectIdentityEqualsVisitor());
-        map.put(x1, 1);
-        assertTrue(map.containsKey(x1));
-        
-        map.remove(x1);
-        
-        assertFalse(map.containsKey(x1));
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorSetTest.java b/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorSetTest.java
deleted file mode 100644
index 1d7730b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/utils/VisitorSetTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*

- * 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.utils;

-

-import static org.junit.Assert.assertEquals;

-import static org.junit.Assert.assertTrue;

-

-import java.util.ArrayList;

-import java.util.HashSet;

-import java.util.Iterator;

-import java.util.List;

-import java.util.Set;

-

-import org.junit.Test;

-

-import com.github.javaparser.JavaParser;

-import com.github.javaparser.ast.CompilationUnit;

-import com.github.javaparser.ast.visitor.ObjectIdentityEqualsVisitor;

-import com.github.javaparser.ast.visitor.ObjectIdentityHashCodeVisitor;

-

-public class VisitorSetTest {

-

-    @Test

-    public void normalEqualsDoesDeepCompare() {

-        Set<CompilationUnit> set = new HashSet<>();

-        set.add(JavaParser.parse("class X{}"));

-        set.add(JavaParser.parse("class X{}"));

-        assertEquals(1, set.size());

-    }

-

-    @Test

-    public void objectIdentityEqualsDoesShallowCompare() {

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        set.add(JavaParser.parse("class X{}"));

-        set.add(JavaParser.parse("class X{}"));

-        assertEquals(2, set.size());

-    }

-

-    @Test

-    public void visitorSetContains() {

-        CompilationUnit x1 = JavaParser.parse("class X{}");

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        set.add(x1);

-        assertTrue(set.contains(x1));

-    }

-

-    @Test

-    public void visitorSetContainsAll() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        set.addAll(list);

-        assertTrue(set.size() == 2 && set.containsAll(list));

-    }

-

-    @Test

-    public void visitorSetIterator() {

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        CompilationUnit x1 = JavaParser.parse("class X{}");

-        set.add(x1);

-        CompilationUnit x2 = JavaParser.parse("class X{}");

-        set.add(x2);

-        Iterator<CompilationUnit> itr = set.iterator();

-        assertEquals(x1, itr.next());

-        itr.remove();

-        assertTrue(set.size() == 1);

-        assertEquals(x2, itr.next());

-        itr.remove();

-        assertTrue(set.size() == 0);

-    }

-

-    @Test

-    public void visitorSetRemove() {

-        CompilationUnit x1 = JavaParser.parse("class X{}");

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        set.add(x1);

-        assertTrue(set.remove(x1));

-    }

-

-    @Test

-    public void visitorSetRemoveAll() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        set.addAll(list);

-        set.removeAll(list);

-        assertTrue(set.size() == 0);

-    }

-

-    @Test

-    public void visitorSetRetainAll() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        set.addAll(list);

-        set.add(JavaParser.parse("class X{}"));

-        set.retainAll(list);

-        assertTrue(set.size() == 2);

-    }

-

-    @Test

-    public void visitorSetToArray() {

-        List<CompilationUnit> list = new ArrayList<>();

-        list.add(JavaParser.parse("class X{}"));

-        list.add(JavaParser.parse("class X{}"));

-        Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),

-                new ObjectIdentityEqualsVisitor());

-        set.addAll(list);

-        for (CompilationUnit u : set.toArray(new CompilationUnit[2]))

-            assertTrue(set.contains(u));

-    }

-}

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
deleted file mode 100644
index 4f9af27..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/version/Java10PostProcessorTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-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;
-import static com.github.javaparser.Providers.provider;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class Java10PostProcessorTest {
-    public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_10));
-
-    @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());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ChangingMethodsFromAClassWithAVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ChangingMethodsFromAClassWithAVisitorTest.java
deleted file mode 100644
index 677cfcc..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ChangingMethodsFromAClassWithAVisitorTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import org.junit.Test;
-
-public class ChangingMethodsFromAClassWithAVisitorTest {
-    @Test
-    public void printingTheCompilationUnitToSystemOutput() throws Exception {
-        try (TestFileToken f = new TestFileToken("test.java")) {
-            MethodChanger_1.main(new String[]{});
-        }
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ChangingMethodsFromAClassWithoutAVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ChangingMethodsFromAClassWithoutAVisitorTest.java
deleted file mode 100644
index 9301ff5..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ChangingMethodsFromAClassWithoutAVisitorTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import org.junit.Test;
-
-public class ChangingMethodsFromAClassWithoutAVisitorTest {
-    @Test
-    public void printingTheCompilationUnitToSystemOutput() throws Exception {
-        try (TestFileToken f = new TestFileToken("test.java")) {
-            MethodChanger_2.main(new String[]{});
-        }
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ClassCreator.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ClassCreator.java
deleted file mode 100644
index 1e1d91b..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/ClassCreator.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Modifier;
-import com.github.javaparser.ast.PackageDeclaration;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.Parameter;
-import com.github.javaparser.ast.expr.*;
-import com.github.javaparser.ast.stmt.BlockStmt;
-import com.github.javaparser.ast.type.ClassOrInterfaceType;
-import com.github.javaparser.ast.type.VoidType;
-
-import java.util.EnumSet;
-
-import static com.github.javaparser.JavaParser.parseClassOrInterfaceType;
-import static com.github.javaparser.JavaParser.parseName;
-
-public class ClassCreator {
-
-    public static void main(String[] args) throws Exception {
-        // creates the compilation unit
-        CompilationUnit cu = createCU();
-
-        // prints the created compilation unit
-        System.out.println(cu.toString());
-    }
-
-    /**
-     * creates the compilation unit
-     */
-    private static CompilationUnit createCU() {
-        CompilationUnit cu = new CompilationUnit();
-        // set the package
-        cu.setPackageDeclaration(new PackageDeclaration(parseName("java.parser.test")));
-
-        // or a shortcut
-        cu.setPackageDeclaration("java.parser.test");
-
-        // create the type declaration 
-        ClassOrInterfaceDeclaration type = cu.addClass("GeneratedClass");
-
-        // create a method
-        EnumSet<Modifier> modifiers = EnumSet.of(Modifier.PUBLIC);
-        MethodDeclaration method = new MethodDeclaration(modifiers, new VoidType(), "main");
-        modifiers.add(Modifier.STATIC);
-        method.setModifiers(modifiers);
-        type.addMember(method);
-        
-        // or a shortcut
-        MethodDeclaration main2 = type.addMethod("main2", Modifier.PUBLIC, Modifier.STATIC);
-
-        // add a parameter to the method
-        Parameter param = new Parameter(parseClassOrInterfaceType("String"), "args");
-        param.setVarArgs(true);
-        method.addParameter(param);
-        
-        // or a shortcut
-        main2.addAndGetParameter(String.class, "args").setVarArgs(true);
-
-        // add a body to the method
-        BlockStmt block = new BlockStmt();
-        method.setBody(block);
-
-        // add a statement to the method body
-        NameExpr clazz = new NameExpr("System");
-        FieldAccessExpr field = new FieldAccessExpr(clazz, "out");
-        MethodCallExpr call = new MethodCallExpr(field, "println");
-        call.addArgument(new StringLiteralExpr("Hello World!"));
-        block.addStatement(call);
-
-        return cu;
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/CreatingACompilationUnitFromScratch.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/CreatingACompilationUnitFromScratch.java
deleted file mode 100644
index fa256d2..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/CreatingACompilationUnitFromScratch.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import org.junit.Test;
-
-public class CreatingACompilationUnitFromScratch {
-    @Test
-    public void printingTheCompilationUnitToSystemOutput() throws Exception {
-        ClassCreator.main(new String[]{});
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/CuPrinter.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/CuPrinter.java
deleted file mode 100644
index 89653f4..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/CuPrinter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-
-import java.io.FileInputStream;
-
-public class CuPrinter {
-
-    public static void main(String[] args) throws Exception {
-        // creates an input stream for the file to be parsed
-        FileInputStream in = new FileInputStream("test.java");
-
-        // parse the file
-        CompilationUnit cu = JavaParser.parse(in);
-
-        // prints the resulting compilation unit to default system output
-        System.out.println(cu.toString());
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodChanger_1.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodChanger_1.java
deleted file mode 100644
index 1d64866..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodChanger_1.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
-
-import java.io.File;
-
-public class MethodChanger_1 {
-
-    public static void main(String[] args) throws Exception {
-        // parse a file
-        CompilationUnit cu = JavaParser.parse(new File("test.java"));
-
-        // visit and change the methods names and parameters
-        cu.accept(new MethodChangerVisitor(), null);
-
-        // prints the changed compilation unit
-        System.out.println(cu);
-    }
-
-    /**
-     * Simple visitor implementation for visiting MethodDeclaration nodes.
-     */
-    private static class MethodChangerVisitor extends VoidVisitorAdapter<Void> {
-        @Override
-        public void visit(MethodDeclaration n, Void arg) {
-            // change the name of the method to upper case
-            n.setName(n.getNameAsString().toUpperCase());
-
-            // add a new parameter to the method
-            n.addParameter("int", "value");
-        }
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodChanger_2.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodChanger_2.java
deleted file mode 100644
index bf0c72d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodChanger_2.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.NodeList;
-import com.github.javaparser.ast.body.BodyDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.body.TypeDeclaration;
-
-import java.io.FileInputStream;
-
-import static com.github.javaparser.ast.type.PrimitiveType.intType;
-
-public class MethodChanger_2 {
-
-    public static void main(String[] args) throws Exception {
-        // creates an input stream for the file to be parsed
-        FileInputStream in = new FileInputStream("test.java");
-        
-        // parse the file
-        CompilationUnit cu = JavaParser.parse(in);
-
-        // change the methods names and parameters
-        changeMethods(cu);
-
-        // prints the changed compilation unit
-        System.out.println(cu.toString());
-    }
-
-    private static void changeMethods(CompilationUnit cu) {
-        // Go through all the types in the file
-        NodeList<TypeDeclaration<?>> types = cu.getTypes();
-        for (TypeDeclaration<?> type : types) {
-            // Go through all fields, methods, etc. in this type
-            NodeList<BodyDeclaration<?>> members = type.getMembers();
-            for (BodyDeclaration<?> member : members) {
-                if (member instanceof MethodDeclaration) {
-                    MethodDeclaration method = (MethodDeclaration) member;
-                    changeMethod(method);
-                }
-            }
-        }
-    }
-
-    private static void changeMethod(MethodDeclaration n) {
-        // change the name of the method to upper case
-        n.setName(n.getNameAsString().toUpperCase());
-
-        // create the new parameter
-        n.addParameter(intType(), "value");
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodPrinter.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodPrinter.java
deleted file mode 100644
index 8e1e5bf..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/MethodPrinter.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
-
-import java.io.FileInputStream;
-
-public class MethodPrinter {
-
-    public static void main(String[] args) throws Exception {
-        // creates an input stream for the file to be parsed
-        FileInputStream in = new FileInputStream("test.java");
-
-        // parse it
-        CompilationUnit cu = JavaParser.parse(in);
-
-        // visit and print the methods names
-        cu.accept(new MethodVisitor(), null);
-    }
-
-    /**
-     * Simple visitor implementation for visiting MethodDeclaration nodes.
-     */
-    private static class MethodVisitor extends VoidVisitorAdapter<Void> {
-        @Override
-        public void visit(MethodDeclaration n, Void arg) {
-            /* here you can access the attributes of the method.
-             this method will be called for all methods in this 
-             CompilationUnit, including inner class methods */
-            System.out.println(n.getName());
-            super.visit(n, arg);
-        }
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/PrintingTheCompilationUnitToSystemOutputTest.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/PrintingTheCompilationUnitToSystemOutputTest.java
deleted file mode 100644
index 26a907e..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/PrintingTheCompilationUnitToSystemOutputTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import org.junit.Test;
-
-public class PrintingTheCompilationUnitToSystemOutputTest {
-    @Test
-    public void printingTheCompilationUnitToSystemOutput() throws Exception {
-        try (TestFileToken f = new TestFileToken("test.java")) {
-            CuPrinter.main(new String[]{});
-        }
-    }
-
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/TestFileToken.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/TestFileToken.java
deleted file mode 100644
index 3227c3d..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/TestFileToken.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import org.apache.commons.io.IOUtils;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import static org.junit.Assert.*;
-
-/**
- * Creates a temporary test file that a sample can use. This way we don't have to rewrite the samples to fit them into
- * these tests.
- */
-public class TestFileToken implements AutoCloseable {
-    private final String filename;
-
-    public TestFileToken(String filename) {
-        this.filename = filename;
-        try {
-            try (InputStream i = getClass().getResourceAsStream("TestFile.java"); OutputStream o = new FileOutputStream(filename)) {
-                assertNotNull(i);
-                IOUtils.copy(i, o);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail(e.getMessage());
-        }
-    }
-
-    @Override
-    public void close() {
-        boolean deleted = new File(filename).delete();
-        assertTrue(deleted);
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/VisitingClassMethodsTest.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/VisitingClassMethodsTest.java
deleted file mode 100644
index 5999124..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/VisitingClassMethodsTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.wiki_samples;
-
-import org.junit.Test;
-
-public class VisitingClassMethodsTest {
-    @Test
-    public void testCode() throws Exception {
-        try (TestFileToken f = new TestFileToken("test.java")) {
-            MethodPrinter.main(new String[]{});
-        }
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/D.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/D.java
deleted file mode 100644
index dd925bc..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/D.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.wiki_samples.removenode;
-
-public class D {
-
-    public void foo(int e) {
-        int a = 20;
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/ModifierVisitorTest.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/ModifierVisitorTest.java
deleted file mode 100644
index d522c96..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/ModifierVisitorTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.wiki_samples.removenode;
-
-import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.Node;
-import com.github.javaparser.ast.body.VariableDeclarator;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.IntegerLiteralExpr;
-import com.github.javaparser.ast.visitor.ModifierVisitor;
-
-import java.io.FileInputStream;
-
-public class ModifierVisitorTest {
-
-    public static void main(String... args) throws Exception {
-        // parse the file
-        CompilationUnit cu = JavaParser.parse(new FileInputStream("forGitHubTest.java"));
-
-        // The visitor should remove all a=20 variable declarations.
-        cu.accept(new MyVisitor(), null);
-
-        System.out.println(cu.toString());
-    }
-}
-
-class MyVisitor extends ModifierVisitor<Void> {
-    @Override
-    public Node visit(VariableDeclarator declarator, Void args) {
-        if (declarator.getNameAsString().equals("a")
-                // the initializer is optional, first check if there is one
-                && declarator.getInitializer().isPresent()) {
-            Expression expression = declarator.getInitializer().get();
-            // We're looking for a literal integer.
-            if (expression instanceof IntegerLiteralExpr) {
-                // We found one. Is it literal integer 20?
-                if (((IntegerLiteralExpr) expression).getValue().equals("20")) {
-                    // Returning null means "remove this VariableDeclarator"
-                    return null;
-                }
-            }
-        }
-        return declarator;
-    }
-}
diff --git a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/RemoveDeleteNodeFromAst.java b/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/RemoveDeleteNodeFromAst.java
deleted file mode 100644
index 72756e9..0000000
--- a/javaparser-testing/src/test/java/com/github/javaparser/wiki_samples/removenode/RemoveDeleteNodeFromAst.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.wiki_samples.removenode;
-
-import com.github.javaparser.wiki_samples.TestFileToken;
-import org.junit.Test;
-
-public class RemoveDeleteNodeFromAst {
-    @Test
-    public void testCode1() throws Exception {
-        try (TestFileToken f = new TestFileToken("forGitHubTest.java")) {
-            ModifierVisitorTest.main();
-        }
-    }
-}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/comment_parsing_scenarios.story b/javaparser-testing/src/test/resources/com/github/javaparser/bdd/comment_parsing_scenarios.story
deleted file mode 100644
index e41d6e4..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/comment_parsing_scenarios.story
+++ /dev/null
@@ -1,281 +0,0 @@
-Scenario: A Class With Line Comments is processed by the Comments Parser
-
-Given the class:
-package japa.parser.comments;
-
-public class ClassWithLineComments {
-
-    public void aMethod(){
-        // first comment
-        int a=0; // second comment
-        // third comment
-        // fourth comment
-    }
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 4
-Then line comment 1 is " first comment"
-Then line comment 2 is " second comment"
-Then line comment 3 is " third comment"
-Then line comment 4 is " fourth comment"
-Then the line comments have the following positions:
-|beginLine|beginColumn|endLine|endColumn|
-|6|9|6|25|
-|7|18|7|35|
-|8|9|8|25|
-|9|9|9|26|
-
-Scenario: A Class With Block Comments is processed by the Comments Parser
-
-Given the class:
-package japa.parser.comments;
-
-/* comment which is not attributed to the class, it floats around as an orphan */
-/* comment to a class */
-public class ClassWithBlockComments {
-
-    /* comment to a method */
-    void foo(){};
-
-    /* comment put randomly in class:
-
-    another orphan.
-    It spans over more lines */
-
-}
-
-/* a comment lost inside a compilation unit. It is orphan, I am sure you got this one */
-When the class is parsed by the comment parser
-Then the total number of comments is 5
-Then block comment 1 is " comment which is not attributed to the class, it floats around as an orphan "
-Then block comment 2 is " comment to a class "
-Then block comment 3 is " comment to a method "
-Then block comment 4 is " comment put randomly in class:    another orphan.    It spans over more lines "
-Then block comment 5 is " a comment lost inside a compilation unit. It is orphan, I am sure you got this one  "
-Then the block comments have the following positions:
-|beginLine|beginColumn|endLine|endColumn|
-|3|1|3|81|
-|4|1|4|24|
-|7|5|7|29|
-|10|5|13|31|
-|17|1|17|88|
-
-
-Scenario: A Class With Javadoc Comments is processed by the Comments Parser
-
-Given the class:
-package japa.parser.comments;
-
-/** a proper javadoc comment */
-public class ClassWithJavadocComments {
-
-    void foo(){};
-
-
-}
-/** a floating javadoc comment */
-When the class is parsed by the comment parser
-Then the total number of comments is 2
-Then Javadoc comment 1 is " a proper javadoc comment "
-Then Javadoc comment 2 is " a floating javadoc comment "
-Then the Javadoc comments have the following positions:
-|beginLine|beginColumn|endLine|endColumn|
-|3|1|3|31|
-|10|1|10|33|
-
-
-
-Scenario: A Class With Orphan Comments is processed by the Comments Parser
-
-Given the class:
-package japa.parser.comments;
-
-/**Javadoc associated with the class*/
-public class ClassWithOrphanComments {
-    //a first comment floating in the class
-
-    //comment associated to the method
-    void foo(){
-        /*comment floating inside the method*/
-    }
-
-    //a second comment floating in the class
-}
-
-//Orphan comment inside the CompilationUnit
-When the class is parsed by the comment parser
-Then the total number of comments is 6
-Then line comment 1 is "a first comment floating in the class"
-Then line comment 2 is "comment associated to the method"
-Then line comment 3 is "a second comment floating in the class"
-Then block comment 1 is "comment floating inside the method"
-Then Javadoc comment 1 is "Javadoc associated with the class"
-
-
-Scenario: A Class With Orphan Comments is processed by the Comments Parser
-
-Given the class:
-/*CompilationUnitComment*/
-package japa.parser.comments;
-
-public class ClassWithMixedStyleComments {
-    // line comment
-    int a = 0;
-    // another line comment
-    int b = 0;
-    // line comment
-    int c = 0;
-    /* multi-line
-       comment
-    */
-    int d = 0;
-    /**
-     * multi-line
-     */
-    int e = 0;
-    // final comment
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 7
-Then the line comments have the following positions:
-|beginLine|beginColumn|endLine|endColumn|
-|5|5|5|20|
-|7|5|7|28|
-|9|5|9|20|
-|19|5|19|21|
-Then the block comments have the following positions:
-|beginLine|beginColumn|endLine|endColumn|
-|1|1|1|26|
-|11|5|13|6|
-Then the Javadoc comments have the following positions:
-|beginLine|beginColumn|endLine|endColumn|
-|15|5|17|7|
-
-Scenario: A method containing two consecutive line comments is parsed correctly
-
-Given the class:
-class A {
-  void aMethod(){
-     // foo
-     // bar
-     int a;
-  }
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 2
-Then line comment 1 is " foo"
-Then line comment 2 is " bar"
-
-Scenario: Comments from a file with an non-UTF-8 encoding are parsed correctly
-
-When read sample "ClassInLatin1" using encoding "ISO-8859-1"
-Then the total number of comments is 3
-Then line comment 2 is " A l'émej in piasì che sent dësgust."
-
-Scenario: Should not recognize /*/ as a comment
-
-Given the class:
-/*/
-class Foo {}
-When the class is parsed by the comment parser
-Then the total number of comments is 0
-
-Given the class:
-/*/
-class Foo {}
-Then the Java parser cannot parse it because of an error
-
-Scenario: Should recognize /*/ inside a block comment
-
-Given the class:
-/* Foo /*/
-When the class is parsed by the comment parser
-Then the total number of comments is 1
-Then block comment 1 is " Foo /"
-
-Scenario: A Class With Character Literal is processed by the Comments Parser
-Given the class:
-class A {
-    /** comment1 */
-    private char c = '"';
-    /** comment2 */
-    private String d;
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 2
-Then Javadoc comment 1 is "comment1"
-Then Javadoc comment 2 is "comment2"
-
-Scenario: Double slash in string does not mess up comments parsing
-Given the class:
-public class b {
-
-    public void m1() {
-        String s = "\\";
-    }
-
-    /**
-     * Comment
-    */
-    public void m2() {
-        return;
-    }
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 1
-
-Scenario: Triple slash in string does not mess up comments parsing
-Given the class:
-public class b {
-
-    public void m1() {
-        String s = "\\\" // still in string";
-    }
-
-    /**
-     * Comment
-    */
-    public void m2() {
-        return;
-    }
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 1
-
-Scenario: Four slashes in string does not mess up comments parsing
-Given the class:
-public class b {
-
-    public void m1() {
-        String s = "\\\\" // out of the string";
-        ;
-    }
-
-    /**
-     * Comment
-    */
-    public void m2() {
-        return;
-    }
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 2
-
-Scenario: Five slashes in string does not mess up comments parsing
-Given the class:
-public class b {
-
-    public void m1() {
-        String s = "\\\\\" // still in string";
-        ;
-    }
-
-    /**
-     * Comment
-    */
-    public void m2() {
-        return;
-    }
-}
-When the class is parsed by the comment parser
-Then the total number of comments is 1
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/pretty_printing_java_concepts.story b/javaparser-testing/src/test/resources/com/github/javaparser/bdd/pretty_printing_java_concepts.story
deleted file mode 100644
index 2b7af19..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/pretty_printing_java_concepts.story
+++ /dev/null
@@ -1,399 +0,0 @@
-Scenario: Check a whole lot of things at once that should be separate tests
-
-Given the class in the file "JavaConcepts.java"
-When the class is parsed by the Java parser
-Then it is printed as:
-package japa.bdd.samples;
-
-import com.github.javaparser.JavaParser;
-import japa.parser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Ignore;
-import java.io.*;
-import java.util.*;
-
-@Ignore
-@Deprecated
-public class JavaConcepts<T extends List<int[]>, X> extends Base implements Serializable {
-
-    static Class clz1 = String.class;
-
-    protected Class clz2 = (String.class);
-
-    Class clz3 = int.class;
-
-    Class clz4 = (int.class);
-
-    int[] arr = new int[10];
-
-    byte bye = 0;
-
-    byte[] byebye = null;
-
-    short sh1, sh2 = 1;
-
-    int intWithUnderscore = 1234_5678;
-
-    long longWithUnderscore = 1234_5678L;
-
-    float floatWithUnderscore = 1_234.5_678f;
-
-    float floatWithUnderscoreAndExponent = 1_234e1_0f;
-
-    double doubleWithUnderscore = 1_234.5_678;
-
-    double doubleWithUnderscoreAndExponent = 1_234e1_0;
-
-    int binaryLiteral = 0b101101;
-
-    List<String>[][] arrLS = (List<String>[][]) new List<?>[10][];
-
-    {
-        int z = 0, y = 0;
-        int a = (z) + y;
-        a = (+z) + y;
-        byte b = (byte) +y;
-    }
-
-    List<String> diamond1 = new LinkedList<>();
-
-    @Deprecated()
-    static class Ugly {
-
-        static int x = 0;
-
-        public static void main(String[] args) {
-            x = +x;
-            x = ~x;
-            --x;
-            boolean b = !false;
-            x &= 2;
-            x |= 2;
-            x ^= 2;
-            x -= 2;
-            x %= 2;
-            x /= 2;
-            x *= 2;
-            x <<= 2;
-            x >>= 2;
-            x >>>= 2;
-            b = b || false;
-            b = b | false;
-            b = b & false;
-            b = b ^ false;
-            b = b != false;
-            b = x > 1;
-            b = x < 1;
-            b = x >= 1;
-            b = x <= 1;
-            x = x << 1;
-            x = x >> 1;
-            x = x >>> 1;
-            x = x - 1;
-            x = x * 1;
-            x = x % 1;
-            x = x / 1;
-        }
-    }
-
-    @Deprecated()
-    int[][][][] arr2 = new int[10][2][1][0];
-
-    volatile float fff = 0x1.fffeP+127f;
-
-    char cc = 'a';
-
-    int[][] arr3 = { { 1, 2 }, { 3, 4 } };
-
-    static int[][] arr4 = {};
-
-    public static JavaConcepts t;
-
-    static {
-        arr4 = new int[][] { { 2 }, { 1 } };
-    }
-
-    {
-        arr3 = new int[][] { { 2 }, { 1 } };
-    }
-
-    public enum Teste {
-
-        asc, def
-    }
-
-    public enum Sexo {
-
-        m, @Deprecated
-        f;
-
-        public enum Sexo_ implements Serializable, Cloneable {
-        }
-
-        private Sexo() {
-        }
-    }
-
-    @Deprecated
-    public enum Enum {
-
-        m(1) {
-
-            @Override
-            void mm() {
-            }
-        }
-        , f(2) {
-
-            void mm() {
-            }
-        }
-        ;
-
-        native void nnn();
-
-        transient int x;
-
-        private Enum(int x) {
-            this.x = x;
-        }
-
-        abstract void mm();
-    }
-
-    strictfp double ddd() {
-        return 0.0;
-    }
-
-    public <T, E> JavaConcepts(int x) {
-        this.arr[0] = x;
-        T val1 = null;
-        E val2 = null;
-        super.<T, E>check2(val1, val2);
-        boolean b = true, y = false;
-        abstract class X {
-
-            int i = 0;
-
-            public <D> X() {
-            }
-
-            public void m() {
-            }
-        }
-        @Deprecated
-        final class Y extends X {
-
-            public Y() {
-                super();
-                JavaConcepts.this.cc = 'c';
-                super.i = 1;
-                Y.super.m();
-            }
-
-            public Y(int y) {
-                super();
-            }
-
-            public Y(long x) {
-                this();
-            }
-        }
-    }
-
-    public <T> JavaConcepts(String str) {
-    }
-
-    private class QWE extends JavaConcepts<List<int[]>, String> {
-
-        @Deprecated
-        final int z = 0;
-
-        int i = (int) -1;
-
-        public QWE(String... x) {
-            <String>super(x[0]);
-        }
-
-        public QWE(int... x) {
-            super(x[0]);
-            i = x[0];
-            assert true;
-            assert 1 == 1 : 2;
-            {
-                int iii = 3;
-                iii += 3;
-            }
-            label: {
-                int iii = 1;
-            }
-            ;
-            ;
-            int min = -2147483648;
-            long sl = 123123123123l;
-            long minl = -9223372036854775808L;
-            switch(i) {
-            }
-            ll: switch(i) {
-                case 1:
-                    System.out.println(1);
-                    break ll;
-                default:
-                    {
-                        System.out.println("default");
-                        break;
-                    }
-                case 2:
-                    if (t instanceof Base) {
-                        System.out.println(1);
-                    }
-                    i++;
-                    ++i;
-            }
-        }
-
-        private synchronized int[] doSomething() {
-            List<? extends Number> x = new ArrayList<Integer>();
-            return new int[] { 1 };
-        }
-    }
-
-    public static void main(String[] args) throws ParseException, IOException {
-        int x = 2;
-        CompilationUnit cu = parse(new File("src/japa/parser/javacc/Parser.java"));
-        System.out.println(cu);
-        JavaConcepts teste = new JavaConcepts(2);
-        JavaConcepts.QWE qwe = teste.new QWE(1);
-        if (1 + 1 == 2) {
-            teste = null;
-            teste = new JavaConcepts(1);
-        } else {
-            x = 3;
-            teste = new JavaConcepts(1);
-            x = x == 0 ? 2 : 4;
-        }
-        if (true)
-            x = 1;
-        else
-            x = 3;
-        if (true)
-            x = 1;
-        else if (false)
-            x = 3;
-        else
-            x = 2;
-        while (true) {
-            xxx: while (x == 3) continue xxx;
-            break;
-        }
-        do {
-            x++;
-        } while (x < 100);
-        do x++; while (x < 100);
-        for (@Deprecated int i : arr4[0]) {
-            x--;
-        }
-        for (@Deprecated final int i = 0, j = 1; i < 10; x++) {
-            break;
-        }
-        int i, j;
-        for (i = 0, j = 1; i < 10 && j < 2; i++, j--) {
-            break;
-        }
-    }
-
-    public static CompilationUnit parse(@Deprecated File file) throws ParseException, IOException {
-        String a = ((String) "qwe");
-        String x = ((String) clz1.getName());
-        int y = ((Integer) (Object) x).intValue();
-        synchronized (file) {
-            file = null;
-            file = new File("");
-        }
-        try {
-            if (file == null) {
-                throw new NullPointerException("blah");
-            }
-        } catch (final NullPointerException e) {
-            System.out.println("catch");
-        } catch (RuntimeException e) {
-            System.out.println("catch");
-        } finally {
-            System.out.println("finally");
-        }
-        try {
-            if (file == null) {
-                throw new NullPointerException("blah");
-            }
-        } finally {
-            System.out.println("finally");
-        }
-        try {
-            if (file == null) {
-                throw new NullPointerException("blah");
-            }
-        } catch (RuntimeException e) {
-            System.out.println("catch");
-        }
-        try (InputStream in = createInputStream()) {
-            System.out.println(in);
-        } catch (IOException e) {
-            System.out.println("catch");
-        }
-        try (InputStream in = createInputStream();
-            InputStream in2 = createInputStream()) {
-            System.out.println(in);
-        } catch (IOException e) {
-            System.out.println("catch");
-        }
-        try (InputStream in = createInputStream()) {
-            System.out.println(in);
-        }
-        try {
-            System.out.println("whatever");
-        } catch (RuntimeException e) {
-            System.out.println(e);
-        } catch (final Exception | Error e) {
-            System.out.println(e);
-        }
-        return JavaParser.parse(file);
-    }
-
-    class A<T extends Integer & Serializable> implements XXX, Serializable {
-
-        public <ABC> A(Integer integer, ABC string) throws Exception, IOException {
-        }
-    }
-
-    private <Y> void x(Map<? extends X, ? super T> x) {
-        @Deprecated Comparator c = new Comparator() {
-
-            public int compare(Object o1, Object o2) {
-                try {
-                    A<Integer> a = new <String> A<Integer>(new Integer(11), "foo") {
-                    };
-                } catch (Exception e) {
-                }
-                return 0;
-            }
-
-            @Override
-            public boolean equals(Object obj) {
-                return super.equals(obj);
-            }
-        };
-    }
-
-    private static InputStream createInputStream() {
-        return new ByteArrayInputStream(null);
-    }
-}
-
-class Base {
-
-    public <A, B> void check2(A val1, B val2) {
-    }
-}
-
-interface XXX extends Serializable, Cloneable {
-}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/pretty_printing_scenarios.story b/javaparser-testing/src/test/resources/com/github/javaparser/bdd/pretty_printing_scenarios.story
deleted file mode 100644
index 5450cb0..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/bdd/pretty_printing_scenarios.story
+++ /dev/null
@@ -1,519 +0,0 @@
-Scenario: When printing the instantiation we should use the right amount of spaces
-
-Given the class:
-public class A {
-    Object foo = new Object();
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class A {
-
-    Object foo = new Object();
-}
-
-
-Scenario: When printing the lambda expression we should use the right indentation
-
-Given the class:
-public class B {
-	Runnable runnable = ()-> System.out.println("running");
-    Consumer<Integer> consumer = i->{ i+=1; System.out.println(i);};
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class B {
-
-    Runnable runnable = () -> System.out.println("running");
-
-    Consumer<Integer> consumer = i -> {
-        i += 1;
-        System.out.println(i);
-    };
-}
-
-
-Scenario: Printing orphan comments in empty method
-Given the class:
-class A {
-    public void helloWorld(String greeting, String name) {
-        //sdfsdfsdf
-            //sdfds
-        /*
-                            dgfdgfdgfdgfdgfd
-         */
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-class A {
-
-    public void helloWorld(String greeting, String name) {
-    // sdfsdfsdf
-    // sdfds
-    /*
-                            dgfdgfdgfdgfdgfd
-         */
-    }
-}
-
-
-
-Scenario: Printing orphan comments in empty method (issue 192)
-Given the class:
-public class StepImplementation {
-    @Step("A step")
-    public void contextStep() {
-        // Foo bar
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class StepImplementation {
-
-    @Step("A step")
-    public void contextStep() {
-    // Foo bar
-    }
-}
-
-
-Scenario: Printing orphan comments in for loop (issue 192)
-Given the class:
-public class StepImplementation {
-    public void contextStep() {
-        for (int i = 0; i < 5; i++) {
-            // foo bar
-        }
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class StepImplementation {
-
-    public void contextStep() {
-        for (int i = 0; i < 5; i++) {
-        // foo bar
-        }
-    }
-}
-
-
-Scenario: Printing orphan and attributed comments in for loop (issue 192)
-Given the class:
-public class StepImplementation {
-public void contextStep() {
-        for (int i = 0; i < 5; i++) {
-            // foo bar
-            System.out.println();
-            // another foo bar
-        }
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class StepImplementation {
-
-    public void contextStep() {
-        for (int i = 0; i < 5; i++) {
-            // foo bar
-            System.out.println();
-        // another foo bar
-        }
-    }
-}
-
-
-Scenario: An empty Enum is printed correctly
-Given the compilation unit:
-package test; enum XYZ {}
-When the class is parsed by the Java parser
-Then it is printed as:
-package test;
-
-enum XYZ {
-}
-
-Scenario: An enum without fields has no () on its members
-Given the compilation unit:
-package test; enum XYZ {A,B,C}
-When the class is parsed by the Java parser
-Then it is printed as:
-package test;
-
-enum XYZ {
-
-    A, B, C
-}
-
-Scenario: Strings with escaped newlines are parsed correctly
-Given the class:
-class A {
-    public void helloWorld(String greeting, String name) {
-        return "hello\nworld";
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-class A {
-
-    public void helloWorld(String greeting, String name) {
-        return "hello\nworld";
-    }
-}
-
-Scenario: A multi-catch is printed correctly
-Given the class:
-class A {
-    public void a() {
-        try {
-        } catch (IndexOutOfBoundException | IOException e) { 
-        } 
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-class A {
-
-    public void a() {
-        try {
-        } catch (IndexOutOfBoundException | IOException e) {
-        }
-    }
-}
-
-Scenario: An empty import does not fail
-Given the class:
-package a.b.c;
-
-;
-When the class is parsed by the Java parser
-Then it is printed as:
-package a.b.c;
-
-Scenario: we can parse blocks
-Given the block:
-{
-    a=2;
-    b=3;
-}
-When the block is parsed by the Java parser
-Then it is printed as:
-{
-    a = 2;
-    b = 3;
-}
-
-Scenario: we can parse statements
-Given the statement:
-while (true) {
-}
-When the statement is parsed by the Java parser
-Then it is printed as:
-while (true) {
-}
-
-Scenario: we can parse static on demand imports
-Given the import:
-import static a.b.c.Abc.*;
-When the import is parsed by the Java parser
-Then it is printed as:
-import static a.b.c.Abc.*;
-
-Scenario: we can parse static type imports
-Given the import:
-import static a.b.c.Abc;
-When the import is parsed by the Java parser
-Then it is printed as:
-import static a.b.c.Abc;
-
-Scenario: we can parse on demand imports
-Given the import:
-import a.b.c.*;
-When the import is parsed by the Java parser
-Then it is printed as:
-import a.b.c.*;
-
-Scenario: we can parse type imports
-Given the import:
-import a.b.c.Abc;
-When the import is parsed by the Java parser
-Then it is printed as:
-import a.b.c.Abc;
-
-Scenario: we can parse annotations
-Given the annotation:
-@Abc
-When the annotation is parsed by the Java parser
-Then it is printed as:
-@Abc
-
-Scenario: we can parse body declarations
-Given the body:
-String author();
-When the annotation body declaration is parsed by the Java parser
-Then it is printed as:
-String author();
-
-Scenario: we can parse class body declarations
-Given the body:
-public int xyz() {}
-When the class body declaration is parsed by the Java parser
-Then it is printed as:
-public int xyz() {
-}
-
-Scenario: we can parse interface body declarations
-Given the body:
-int xyz();
-When the interface body declaration is parsed by the Java parser
-Then it is printed as:
-int xyz();
-
-Scenario: It doesn't throw NPE when using a modifierVisitorAdapter
-Given the class:
-public class Example {
-  private String mString;
-  public Example(String arg) {
-    mString = arg;
-  }
-}
-When the class is parsed by the Java parser
-When the class is visited by an empty ModifierVisitorAdapter
-Then it is printed as:
-public class Example {
-
-    private String mString;
-
-    public Example(String arg) {
-        mString = arg;
-    }
-}
-
-Scenario: JavaDoc OR comment is printed, not both.
-Given the class:
-public class Foo {
-    /** This line gets duplicated */
-    public void foo() {
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class Foo {
-
-    /**
-     * This line gets duplicated
-     */
-    public void foo() {
-    }
-}
-
-Scenario: various lamba casts (issue 418)
-Given the class:
-public class TestLambda {
-    void okMethod() {
-        return (ITF) () -> {
-            return true;
-        };
-    }
-    void faliingMethod() {
-        testThis(check ? null : (ITF) () -> {
-            return true;
-        });
-    }
-}
-When the class body declaration is parsed by the Java parser
-Then it is printed as:
-public class TestLambda {
-
-    void okMethod() {
-        return (ITF) () -> {
-            return true;
-        };
-    }
-
-    void faliingMethod() {
-        testThis(check ? null : (ITF) () -> {
-            return true;
-        });
-    }
-}
-
-Scenario: Duplicate methods are not a parsing error (#416)
-Given the class:
-public class Foo {
-    public void foo() {
-    }
-    public void foo() {
-    }
-    public void foo() {
-    }
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class Foo {
-
-    public void foo() {
-    }
-
-    public void foo() {
-    }
-
-    public void foo() {
-    }
-}
-
-Scenario: Both array syntaxes are supported (#416)
-Given the class:
-public class Foo {
-    public void m1(boolean[] boolArray) {}
-    public void m1(boolean boolArray[]) {}
-    public void m1(boolean[] boolArray[]) {}
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-public class Foo {
-
-    public void m1(boolean[] boolArray) {
-    }
-
-    public void m1(boolean[] boolArray) {
-    }
-
-    public void m1(boolean[][] boolArray) {
-    }
-}
-
-
-Scenario: Array parts can be annotated
-Given the class:
-class Foo {
-    void m1(@Boo boolean @Index1 [] @ Index2 [] boolArray) {}
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-class Foo {
-
-    void m1(@Boo boolean @Index1 [] @Index2 [] boolArray) {
-    }
-}
-
-Scenario: Annotations are supported on annotations
-Given the class:
-@C @interface D {
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-@C
-@interface D {
-}
-
-Scenario: Annotations are supported on interfaces
-Given the class:
-@C interface Abc {
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-@C
-interface Abc {
-}
-
-Scenario: Annotations are supported on enums
-Given the class:
-@C enum Abc {
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-@C
-enum Abc {
-}
-
-Scenario: Annotations are supported on classes (issue 436 is the commented part)
-Given the compilation unit:
-@C
-public class Abc<@C A, @C X extends @C String & @C Serializable> {
-
-	@C int @C[] @C []f;
-
-	@C
-	public Abc(@C int p, List<@C ? extends Object> aa){
-		@C int b;
-	}
-	public @C void a(@C int o) {
-/*		try {
-			throw new IOException();
-		} catch (@C NullPointerException | @C IOException e) {
-		}
-*/	}
-}
-When the compilation unit is parsed by the Java parser
-Then it is printed as:
-@C
-public class Abc<@C A, @C X extends @C String & @C Serializable> {
-
-    @C
-    int @C [] @C [] f;
-
-    @C
-    public Abc(@C int p, List<@C ? extends Object> aa) {
-        @C int b;
-    }
-
-    @C
-    public void a(@C int o) {
-    /*		try {
-			throw new IOException();
-		} catch (@C NullPointerException | @C IOException e) {
-		}
-*/
-    }
-}
-
-
-Scenario: Annotations are supported inside catch (issue 436)
-Given the compilation unit:
-public class Abc {
-	public void a() {
-		try {
-		} catch (@C NullPointerException | @C IOException e) {
-		}
-	}
-}
-When the compilation unit is parsed by the Java parser
-Then it is printed as:
-public class Abc {
-
-    public void a() {
-        try {
-        } catch (@C NullPointerException | @C IOException e) {
-        }
-    }
-}
-
-Scenario: Inner class notation does not confuse annotations (#107)
-Given the class:
-class A extends @Ann1 B.@Ann2 C {
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-class A extends @Ann1 B.@Ann2 C {
-}
-
-Scenario: Make sure interface extends can be annotated
-Given the class:
-interface A extends @X B, @Y C, @Z D {
-}
-When the class is parsed by the Java parser
-Then it is printed as:
-interface A extends @X B, @Y C, @Z D {
-}
-
-Scenario: default modifier isn't printed twice
-Given the class:
-interface X {default String author(){}}
-When the annotation body declaration is parsed by the Java parser
-Then it is printed as:
-interface X {
-
-    default String author() {
-    }
-}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example10_expected.java.txt b/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example10_expected.java.txt
deleted file mode 100644
index 1313788..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example10_expected.java.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-// some example
-/** Super extra cool this annotation!!!*/
-public @interface ClassPreamble {
-   String author();
-   String date();
-   int currentRevision() default 1;
-   String lastModified() default "N/A";
-   String lastModifiedBy() default "N/A";
-   // Note use of array
-   String[] reviewers();
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example8_expected.java.txt b/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example8_expected.java.txt
deleted file mode 100644
index 2a5fd93..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/lexical_preservation_samples/AnnotationDeclaration_Example8_expected.java.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-// some example
-
-/** Cool this annotation!*/
-public @interface ClassPreamble {
-   String author();
-   String date();
-   int currentRevision() default 1;
-   String lastModified() default "N/A";
-   String lastModifiedBy() default "N/A";
-   // Note use of array
-   String[] reviewers();
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/printer/JavaConcepts_prettyprinted b/javaparser-testing/src/test/resources/com/github/javaparser/printer/JavaConcepts_prettyprinted
deleted file mode 100644
index c83d8e4..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/printer/JavaConcepts_prettyprinted
+++ /dev/null
@@ -1,395 +0,0 @@
-package japa.bdd.samples;
-
-import com.github.javaparser.JavaParser;
-import japa.parser.ParseException;
-import com.github.javaparser.ast.CompilationUnit;
-import org.junit.Ignore;
-import java.io.*;
-import java.util.*;
-
-@Ignore
-@Deprecated
-public class JavaConcepts<T extends List<int[]>, X> extends Base implements Serializable {
-
-    static Class clz1 = String.class;
-
-    protected Class clz2 = (String.class);
-
-    Class clz3 = int.class;
-
-    Class clz4 = (int.class);
-
-    int[] arr = new int[10];
-
-    byte bye = 0;
-
-    byte[] byebye = null;
-
-    short sh1, sh2 = 1;
-
-    int intWithUnderscore = 1234_5678;
-
-    long longWithUnderscore = 1234_5678L;
-
-    float floatWithUnderscore = 1_234.5_678f;
-
-    float floatWithUnderscoreAndExponent = 1_234e1_0f;
-
-    double doubleWithUnderscore = 1_234.5_678;
-
-    double doubleWithUnderscoreAndExponent = 1_234e1_0;
-
-    int binaryLiteral = 0b101101;
-
-    List<String>[][] arrLS = (List<String>[][]) new List<?>[10][];
-
-    {
-        int z = 0, y = 0;
-        int a = (z) + y;
-        a = (+z) + y;
-        byte b = (byte) +y;
-    }
-
-    List<String> diamond1 = new LinkedList<>();
-
-    @Deprecated()
-    static class Ugly {
-
-        static int x = 0;
-
-        public static void main(String[] args) {
-            x = +x;
-            x = ~x;
-            --x;
-            boolean b = !false;
-            x &= 2;
-            x |= 2;
-            x ^= 2;
-            x -= 2;
-            x %= 2;
-            x /= 2;
-            x *= 2;
-            x <<= 2;
-            x >>= 2;
-            x >>>= 2;
-            b = b || false;
-            b = b | false;
-            b = b & false;
-            b = b ^ false;
-            b = b != false;
-            b = x > 1;
-            b = x < 1;
-            b = x >= 1;
-            b = x <= 1;
-            x = x << 1;
-            x = x >> 1;
-            x = x >>> 1;
-            x = x - 1;
-            x = x * 1;
-            x = x % 1;
-            x = x / 1;
-        }
-    }
-
-    @Deprecated()
-    int[][][][] arr2 = new int[10][2][1][0];
-
-    volatile float fff = 0x1.fffeP+127f;
-
-    char cc = 'a';
-
-    int[][] arr3 = { { 1, 2 }, { 3, 4 } };
-
-    static int[][] arr4 = {};
-
-    public static JavaConcepts t;
-
-    static {
-        arr4 = new int[][] { { 2 }, { 1 } };
-    }
-
-    {
-        arr3 = new int[][] { { 2 }, { 1 } };
-    }
-
-    public enum Teste {
-
-        asc, def
-    }
-
-    public enum Sexo {
-
-        m, @Deprecated
-        f;
-
-        public enum Sexo_ implements Serializable, Cloneable {
-
-        }
-
-        private Sexo() {
-        }
-    }
-
-    @Deprecated
-    public enum Enum {
-
-        m(1) {
-
-            @Override
-            void mm() {
-            }
-        }
-        , f(2) {
-
-            void mm() {
-            }
-        }
-        ;
-
-        native void nnn();
-
-        transient int x;
-
-        private Enum(int x) {
-            this.x = x;
-        }
-
-        abstract void mm();
-    }
-
-    strictfp double ddd() {
-        return 0.0;
-    }
-
-    public <T, E> JavaConcepts(int x) {
-        this.arr[0] = x;
-        T val1 = null;
-        E val2 = null;
-        super.<T, E>check2(val1, val2);
-        boolean b = true, y = false;
-        abstract class X {
-
-            int i = 0;
-
-            public <D> X() {
-            }
-
-            public void m() {
-            }
-        }
-        @Deprecated
-        final class Y extends X {
-
-            public Y() {
-                super();
-                JavaConcepts.this.cc = 'c';
-                super.i = 1;
-                Y.super.m();
-            }
-
-            public Y(int y) {
-                super();
-            }
-
-            public Y(long x) {
-                this();
-            }
-        }
-    }
-
-    public <T> JavaConcepts(String str) {
-    }
-
-    private class QWE extends JavaConcepts<List<int[]>, String> {
-
-        @Deprecated
-        final int z = 0;
-
-        int i = (int) -1;
-
-        public QWE(String... x) {
-            <String>super(x[0]);
-        }
-
-        public QWE(int... x) {
-            super(x[0]);
-            i = x[0];
-            assert true;
-            assert 1 == 1 : 2;
-            {
-                int iii = 3;
-                iii += 3;
-            }
-            label: {
-                int iii = 1;
-            }
-            ;
-            ;
-            int min = -2147483648;
-            long sl = 123123123123l;
-            long minl = -9223372036854775808L;
-            switch(i) {
-            }
-            ll: switch(i) {
-                case 1:
-                    System.out.println(1);
-                    break ll;
-                default:
-                    {
-                        System.out.println("default");
-                        break;
-                    }
-                case 2:
-                    if (t instanceof Base) {
-                        System.out.println(1);
-                    }
-                    i++;
-                    ++i;
-            }
-        }
-
-        private synchronized int[] doSomething() {
-            List<? extends Number> x = new ArrayList<Integer>();
-            return new int[] { 1 };
-        }
-    }
-
-    public static void main(String[] args) throws ParseException, IOException {
-        int x = 2;
-        CompilationUnit cu = parse(new File("src/japa/parser/javacc/Parser.java"));
-        System.out.println(cu);
-        JavaConcepts teste = new JavaConcepts(2);
-        JavaConcepts.QWE qwe = teste.new QWE(1);
-        if (1 + 1 == 2) {
-            teste = null;
-            teste = new JavaConcepts(1);
-        } else {
-            x = 3;
-            teste = new JavaConcepts(1);
-            x = x == 0 ? 2 : 4;
-        }
-        if (true)
-            x = 1;
-        else
-            x = 3;
-        if (true)
-            x = 1;
-        else if (false)
-            x = 3;
-        else
-            x = 2;
-        while (true) {
-            xxx: while (x == 3) continue xxx;
-            break;
-        }
-        do {
-            x++;
-        } while (x < 100);
-        do x++; while (x < 100);
-        for (@Deprecated int i : arr4[0]) {
-            x--;
-        }
-        for (@Deprecated final int i = 0, j = 1; i < 10; x++) {
-            break;
-        }
-        int i, j;
-        for (i = 0, j = 1; i < 10 && j < 2; i++, j--) {
-            break;
-        }
-    }
-
-    public static CompilationUnit parse(@Deprecated File file) throws ParseException, IOException {
-        String a = ((String) "qwe");
-        String x = ((String) clz1.getName());
-        int y = ((Integer) (Object) x).intValue();
-        synchronized (file) {
-            file = null;
-            file = new File("");
-        }
-        try {
-            if (file == null) {
-                throw new NullPointerException("blah");
-            }
-        } catch (final NullPointerException e) {
-            System.out.println("catch");
-        } catch (RuntimeException e) {
-            System.out.println("catch");
-        } finally {
-            System.out.println("finally");
-        }
-        try {
-            if (file == null) {
-                throw new NullPointerException("blah");
-            }
-        } finally {
-            System.out.println("finally");
-        }
-        try {
-            if (file == null) {
-                throw new NullPointerException("blah");
-            }
-        } catch (RuntimeException e) {
-            System.out.println("catch");
-        }
-        try (InputStream in = createInputStream()) {
-            System.out.println(in);
-        } catch (IOException e) {
-            System.out.println("catch");
-        }
-        try (InputStream in = createInputStream();
-            InputStream in2 = createInputStream()) {
-            System.out.println(in);
-        } catch (IOException e) {
-            System.out.println("catch");
-        }
-        try (InputStream in = createInputStream()) {
-            System.out.println(in);
-        }
-        try {
-            System.out.println("whatever");
-        } catch (RuntimeException e) {
-            System.out.println(e);
-        } catch (final Exception | Error e) {
-            System.out.println(e);
-        }
-        return JavaParser.parse(file);
-    }
-
-    class A<T extends Integer & Serializable> implements XXX, Serializable {
-
-        public <ABC> A(Integer integer, ABC string) throws Exception, IOException {
-        }
-    }
-
-    private <Y> void x(Map<? extends X, ? super T> x) {
-        @Deprecated Comparator c = new Comparator() {
-
-            public int compare(Object o1, Object o2) {
-                try {
-                    A<Integer> a = new <String> A<Integer>(new Integer(11), "foo") {
-                    };
-                } catch (Exception e) {
-                }
-                return 0;
-            }
-
-            @Override
-            public boolean equals(Object obj) {
-                return super.equals(obj);
-            }
-        };
-    }
-
-    private static InputStream createInputStream() {
-        return new ByteArrayInputStream(null);
-    }
-}
-
-class Base {
-
-    public <A, B> void check2(A val1, B val2) {
-    }
-}
-
-interface XXX extends Serializable, Cloneable {
-}
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/printer/PrettyPrintVisitor_prettyprinted b/javaparser-testing/src/test/resources/com/github/javaparser/printer/PrettyPrintVisitor_prettyprinted
deleted file mode 100644
index 90048cf..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/printer/PrettyPrintVisitor_prettyprinted
+++ /dev/null
@@ -1,1353 +0,0 @@
-/*
- * 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.printer;
-
-import com.github.javaparser.ast.*;
-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.nodeTypes.NodeWithTypeArguments;
-import com.github.javaparser.ast.nodeTypes.NodeWithVariables;
-import com.github.javaparser.ast.stmt.*;
-import com.github.javaparser.ast.type.*;
-import com.github.javaparser.ast.visitor.VoidVisitor;
-import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.stream.Collectors;
-import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition;
-import static com.github.javaparser.utils.Utils.isNullOrEmpty;
-
-/**
- * Outputs the AST as formatted Java source code.
- *
- * @author Julio Vilmar Gesser
- */
-public class PrettyPrintVisitor implements VoidVisitor<Void> {
-
-    protected final PrettyPrinterConfiguration configuration;
-
-    protected final SourcePrinter printer;
-
-    public PrettyPrintVisitor(PrettyPrinterConfiguration prettyPrinterConfiguration) {
-        configuration = prettyPrinterConfiguration;
-        printer = new SourcePrinter(configuration.getIndent());
-    }
-
-    public String getSource() {
-        return printer.getSource();
-    }
-
-    private void printModifiers(final EnumSet<Modifier> modifiers) {
-        if (modifiers.size() > 0) {
-            printer.print(modifiers.stream().map(Modifier::asString).collect(Collectors.joining(" ")) + " ");
-        }
-    }
-
-    private void printMembers(final NodeList<BodyDeclaration<?>> members, final Void arg) {
-        for (final BodyDeclaration<?> member : members) {
-            printer.println();
-            member.accept(this, arg);
-            printer.println();
-        }
-    }
-
-    private void printMemberAnnotations(final NodeList<AnnotationExpr> annotations, final Void arg) {
-        if (annotations.isEmpty()) {
-            return;
-        }
-        for (final AnnotationExpr a : annotations) {
-            a.accept(this, arg);
-            printer.println();
-        }
-    }
-
-    private void printAnnotations(final NodeList<AnnotationExpr> annotations, boolean prefixWithASpace, final Void arg) {
-        if (annotations.isEmpty()) {
-            return;
-        }
-        if (prefixWithASpace) {
-            printer.print(" ");
-        }
-        for (AnnotationExpr annotation : annotations) {
-            annotation.accept(this, arg);
-            printer.print(" ");
-        }
-    }
-
-    private void printTypeArgs(final NodeWithTypeArguments<?> nodeWithTypeArguments, final Void arg) {
-        NodeList<Type> typeArguments = nodeWithTypeArguments.getTypeArguments().orElse(null);
-        if (!isNullOrEmpty(typeArguments)) {
-            printer.print("<");
-            for (final Iterator<Type> i = typeArguments.iterator(); i.hasNext(); ) {
-                final Type t = i.next();
-                t.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-            printer.print(">");
-        }
-    }
-
-    private void printTypeParameters(final NodeList<TypeParameter> args, final Void arg) {
-        if (!isNullOrEmpty(args)) {
-            printer.print("<");
-            for (final Iterator<TypeParameter> i = args.iterator(); i.hasNext(); ) {
-                final TypeParameter t = i.next();
-                t.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-            printer.print(">");
-        }
-    }
-
-    private void printArguments(final NodeList<Expression> args, final Void arg) {
-        printer.print("(");
-        if (!isNullOrEmpty(args)) {
-            for (final Iterator<Expression> i = args.iterator(); i.hasNext(); ) {
-                final Expression e = i.next();
-                e.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.print(")");
-    }
-
-    private void printJavaComment(final Comment javacomment, final Void arg) {
-        if (javacomment != null) {
-            javacomment.accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final CompilationUnit n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getPackageDeclaration().isPresent()) {
-            n.getPackageDeclaration().get().accept(this, arg);
-        }
-        n.getImports().accept(this, arg);
-        if (!n.getImports().isEmpty()) {
-            printer.println();
-        }
-        for (final Iterator<TypeDeclaration<?>> i = n.getTypes().iterator(); i.hasNext(); ) {
-            i.next().accept(this, arg);
-            printer.println();
-            if (i.hasNext()) {
-                printer.println();
-            }
-        }
-        printOrphanCommentsEnding(n);
-    }
-
-    @Override
-    public void visit(final PackageDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
-        printer.print("package ");
-        n.getName().accept(this, arg);
-        printer.println(";");
-        printer.println();
-        printOrphanCommentsEnding(n);
-    }
-
-    @Override
-    public void visit(final NameExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getName().accept(this, arg);
-        printOrphanCommentsEnding(n);
-    }
-
-    @Override
-    public void visit(final Name n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getQualifier().isPresent()) {
-            n.getQualifier().get().accept(this, arg);
-            printer.print(".");
-        }
-        printer.print(n.getIdentifier());
-        printOrphanCommentsEnding(n);
-    }
-
-    @Override
-    public void visit(SimpleName n, Void arg) {
-        printer.print(n.getIdentifier());
-    }
-
-    @Override
-    public void visit(final ClassOrInterfaceDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        printModifiers(n.getModifiers());
-        if (n.isInterface()) {
-            printer.print("interface ");
-        } else {
-            printer.print("class ");
-        }
-        n.getName().accept(this, arg);
-        printTypeParameters(n.getTypeParameters(), arg);
-        if (!n.getExtendedTypes().isEmpty()) {
-            printer.print(" extends ");
-            for (final Iterator<ClassOrInterfaceType> i = n.getExtendedTypes().iterator(); i.hasNext(); ) {
-                final ClassOrInterfaceType c = i.next();
-                c.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        if (!n.getImplementedTypes().isEmpty()) {
-            printer.print(" implements ");
-            for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) {
-                final ClassOrInterfaceType c = i.next();
-                c.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.println(" {");
-        printer.indent();
-        if (!isNullOrEmpty(n.getMembers())) {
-            printMembers(n.getMembers(), arg);
-        }
-        printOrphanCommentsEnding(n);
-        printer.unindent();
-        printer.print("}");
-    }
-
-    @Override
-    public void visit(final JavadocComment n, final Void arg) {
-        printer.print("/**");
-        printer.print(n.getContent());
-        printer.println("*/");
-    }
-
-    @Override
-    public void visit(final ClassOrInterfaceType n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getScope().isPresent()) {
-            n.getScope().get().accept(this, arg);
-            printer.print(".");
-        }
-        for (AnnotationExpr ae : n.getAnnotations()) {
-            ae.accept(this, arg);
-            printer.print(" ");
-        }
-        n.getName().accept(this, arg);
-        if (n.isUsingDiamondOperator()) {
-            printer.print("<>");
-        } else {
-            printTypeArgs(n, arg);
-        }
-    }
-
-    @Override
-    public void visit(final TypeParameter n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        for (AnnotationExpr ann : n.getAnnotations()) {
-            ann.accept(this, arg);
-            printer.print(" ");
-        }
-        n.getName().accept(this, arg);
-        if (!isNullOrEmpty(n.getTypeBound())) {
-            printer.print(" extends ");
-            for (final Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext(); ) {
-                final ClassOrInterfaceType c = i.next();
-                c.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(" & ");
-                }
-            }
-        }
-    }
-
-    @Override
-    public void visit(final PrimitiveType n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), true, arg);
-        printer.print(n.getType().asString());
-    }
-
-    @Override
-    public void visit(final ArrayType n, final Void arg) {
-        final List<ArrayType> arrayTypeBuffer = new LinkedList<>();
-        Type type = n;
-        while (type instanceof ArrayType) {
-            final ArrayType arrayType = (ArrayType) type;
-            arrayTypeBuffer.add(arrayType);
-            type = arrayType.getComponentType();
-        }
-        type.accept(this, arg);
-        for (ArrayType arrayType : arrayTypeBuffer) {
-            printAnnotations(arrayType.getAnnotations(), true, arg);
-            printer.print("[]");
-        }
-    }
-
-    @Override
-    public void visit(final ArrayCreationLevel n, final Void arg) {
-        printAnnotations(n.getAnnotations(), true, arg);
-        printer.print("[");
-        if (n.getDimension().isPresent()) {
-            n.getDimension().get().accept(this, arg);
-        }
-        printer.print("]");
-    }
-
-    @Override
-    public void visit(final IntersectionType n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
-        boolean isFirst = true;
-        for (ReferenceType element : n.getElements()) {
-            element.accept(this, arg);
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                printer.print(" & ");
-            }
-        }
-    }
-
-    @Override
-    public void visit(final UnionType n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), true, arg);
-        boolean isFirst = true;
-        for (ReferenceType element : n.getElements()) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                printer.print(" | ");
-            }
-            element.accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final WildcardType n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
-        printer.print("?");
-        if (n.getExtendedTypes().isPresent()) {
-            printer.print(" extends ");
-            n.getExtendedTypes().get().accept(this, arg);
-        }
-        if (n.getSuperTypes().isPresent()) {
-            printer.print(" super ");
-            n.getSuperTypes().get().accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final UnknownType n, final Void arg) {
-    // Nothing to print
-    }
-
-    @Override
-    public void visit(final FieldDeclaration n, final Void arg) {
-        printOrphanCommentsBeforeThisChildNode(n);
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        printModifiers(n.getModifiers());
-        if (!n.getVariables().isEmpty()) {
-            n.getMaximumCommonType().accept(this, arg);
-        }
-        printer.print(" ");
-        for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) {
-            final VariableDeclarator var = i.next();
-            var.accept(this, arg);
-            if (i.hasNext()) {
-                printer.print(", ");
-            }
-        }
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final VariableDeclarator n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getName().accept(this, arg);
-        Type commonType = n.getAncestorOfType(NodeWithVariables.class).get().getMaximumCommonType();
-        Type type = n.getType();
-        ArrayType arrayType = null;
-        for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) {
-            if (arrayType == null) {
-                arrayType = (ArrayType) type;
-            } else {
-                arrayType = (ArrayType) arrayType.getComponentType();
-            }
-            printAnnotations(arrayType.getAnnotations(), true, arg);
-            printer.print("[]");
-        }
-        if (n.getInitializer().isPresent()) {
-            printer.print(" = ");
-            n.getInitializer().get().accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final ArrayInitializerExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("{");
-        if (!isNullOrEmpty(n.getValues())) {
-            printer.print(" ");
-            for (final Iterator<Expression> i = n.getValues().iterator(); i.hasNext(); ) {
-                final Expression expr = i.next();
-                expr.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-            printer.print(" ");
-        }
-        printer.print("}");
-    }
-
-    @Override
-    public void visit(final VoidType n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
-        printer.print("void");
-    }
-
-    @Override
-    public void visit(final ArrayAccessExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getName().accept(this, arg);
-        printer.print("[");
-        n.getIndex().accept(this, arg);
-        printer.print("]");
-    }
-
-    @Override
-    public void visit(final ArrayCreationExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("new ");
-        n.getElementType().accept(this, arg);
-        for (ArrayCreationLevel level : n.getLevels()) {
-            level.accept(this, arg);
-        }
-        if (n.getInitializer().isPresent()) {
-            printer.print(" ");
-            n.getInitializer().get().accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final AssignExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getTarget().accept(this, arg);
-        printer.print(" ");
-        printer.print(n.getOperator().asString());
-        printer.print(" ");
-        n.getValue().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final BinaryExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getLeft().accept(this, arg);
-        printer.print(" ");
-        printer.print(n.getOperator().asString());
-        printer.print(" ");
-        n.getRight().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final CastExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("(");
-        n.getType().accept(this, arg);
-        printer.print(") ");
-        n.getExpression().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final ClassExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getType().accept(this, arg);
-        printer.print(".class");
-    }
-
-    @Override
-    public void visit(final ConditionalExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getCondition().accept(this, arg);
-        printer.print(" ? ");
-        n.getThenExpr().accept(this, arg);
-        printer.print(" : ");
-        n.getElseExpr().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final EnclosedExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("(");
-        if (n.getInner().isPresent()) {
-            n.getInner().get().accept(this, arg);
-        }
-        printer.print(")");
-    }
-
-    @Override
-    public void visit(final FieldAccessExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getScope().isPresent())
-            n.getScope().get().accept(this, arg);
-        printer.print(".");
-        n.getName().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final InstanceOfExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getExpression().accept(this, arg);
-        printer.print(" instanceof ");
-        n.getType().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final CharLiteralExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("'");
-        printer.print(n.getValue());
-        printer.print("'");
-    }
-
-    @Override
-    public void visit(final DoubleLiteralExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print(n.getValue());
-    }
-
-    @Override
-    public void visit(final IntegerLiteralExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print(n.getValue());
-    }
-
-    @Override
-    public void visit(final LongLiteralExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print(n.getValue());
-    }
-
-    @Override
-    public void visit(final StringLiteralExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("\"");
-        printer.print(n.getValue());
-        printer.print("\"");
-    }
-
-    @Override
-    public void visit(final BooleanLiteralExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print(String.valueOf(n.getValue()));
-    }
-
-    @Override
-    public void visit(final NullLiteralExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("null");
-    }
-
-    @Override
-    public void visit(final ThisExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getClassExpr().isPresent()) {
-            n.getClassExpr().get().accept(this, arg);
-            printer.print(".");
-        }
-        printer.print("this");
-    }
-
-    @Override
-    public void visit(final SuperExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getClassExpr().isPresent()) {
-            n.getClassExpr().get().accept(this, arg);
-            printer.print(".");
-        }
-        printer.print("super");
-    }
-
-    @Override
-    public void visit(final MethodCallExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getScope().isPresent()) {
-            n.getScope().get().accept(this, arg);
-            printer.print(".");
-        }
-        printTypeArgs(n, arg);
-        n.getName().accept(this, arg);
-        printArguments(n.getArguments(), arg);
-    }
-
-    @Override
-    public void visit(final ObjectCreationExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getScope().isPresent()) {
-            n.getScope().get().accept(this, arg);
-            printer.print(".");
-        }
-        printer.print("new ");
-        printTypeArgs(n, arg);
-        if (!isNullOrEmpty(n.getTypeArguments().orElse(null))) {
-            printer.print(" ");
-        }
-        n.getType().accept(this, arg);
-        printArguments(n.getArguments(), arg);
-        if (n.getAnonymousClassBody().isPresent()) {
-            printer.println(" {");
-            printer.indent();
-            printMembers(n.getAnonymousClassBody().get(), arg);
-            printer.unindent();
-            printer.print("}");
-        }
-    }
-
-    @Override
-    public void visit(final UnaryExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getOperator().isPrefix()) {
-            printer.print(n.getOperator().asString());
-        }
-        n.getExpression().accept(this, arg);
-        if (n.getOperator().isPostfix()) {
-            printer.print(n.getOperator().asString());
-        }
-    }
-
-    @Override
-    public void visit(final ConstructorDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        printModifiers(n.getModifiers());
-        printTypeParameters(n.getTypeParameters(), arg);
-        if (n.isGeneric()) {
-            printer.print(" ");
-        }
-        n.getName().accept(this, arg);
-        printer.print("(");
-        if (!n.getParameters().isEmpty()) {
-            for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) {
-                final Parameter p = i.next();
-                p.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.print(")");
-        if (!isNullOrEmpty(n.getThrownExceptions())) {
-            printer.print(" throws ");
-            for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) {
-                final ReferenceType name = i.next();
-                name.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.print(" ");
-        n.getBody().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final MethodDeclaration n, final Void arg) {
-        printOrphanCommentsBeforeThisChildNode(n);
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        printModifiers(n.getModifiers());
-        if (n.isDefault()) {
-            printer.print("default ");
-        }
-        printTypeParameters(n.getTypeParameters(), arg);
-        if (!isNullOrEmpty(n.getTypeParameters())) {
-            printer.print(" ");
-        }
-        n.getType().accept(this, arg);
-        printer.print(" ");
-        n.getName().accept(this, arg);
-        printer.print("(");
-        if (!isNullOrEmpty(n.getParameters())) {
-            for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) {
-                final Parameter p = i.next();
-                p.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.print(")");
-        if (!isNullOrEmpty(n.getThrownExceptions())) {
-            printer.print(" throws ");
-            for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) {
-                final ReferenceType name = i.next();
-                name.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        if (!n.getBody().isPresent()) {
-            printer.print(";");
-        } else {
-            printer.print(" ");
-            n.getBody().get().accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final Parameter n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
-        printModifiers(n.getModifiers());
-        if (n.getType() != null) {
-            n.getType().accept(this, arg);
-        }
-        if (n.isVarArgs()) {
-            printer.print("...");
-        }
-        printer.print(" ");
-        n.getName().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final ExplicitConstructorInvocationStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.isThis()) {
-            printTypeArgs(n, arg);
-            printer.print("this");
-        } else {
-            if (n.getExpression().isPresent()) {
-                n.getExpression().get().accept(this, arg);
-                printer.print(".");
-            }
-            printTypeArgs(n, arg);
-            printer.print("super");
-        }
-        printArguments(n.getArguments(), arg);
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final VariableDeclarationExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printAnnotations(n.getAnnotations(), false, arg);
-        printModifiers(n.getModifiers());
-        if (!n.getVariables().isEmpty()) {
-            n.getMaximumCommonType().accept(this, arg);
-        }
-        printer.print(" ");
-        for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) {
-            final VariableDeclarator v = i.next();
-            v.accept(this, arg);
-            if (i.hasNext()) {
-                printer.print(", ");
-            }
-        }
-    }
-
-    @Override
-    public void visit(final LocalClassDeclarationStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getClassDeclaration().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final AssertStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("assert ");
-        n.getCheck().accept(this, arg);
-        if (n.getMessage().isPresent()) {
-            printer.print(" : ");
-            n.getMessage().get().accept(this, arg);
-        }
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final BlockStmt n, final Void arg) {
-        printOrphanCommentsBeforeThisChildNode(n);
-        printJavaComment(n.getComment(), arg);
-        printer.println("{");
-        if (n.getStatements() != null) {
-            printer.indent();
-            for (final Statement s : n.getStatements()) {
-                s.accept(this, arg);
-                printer.println();
-            }
-            printer.unindent();
-        }
-        printOrphanCommentsEnding(n);
-        printer.print("}");
-    }
-
-    @Override
-    public void visit(final LabeledStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getLabel().accept(this, arg);
-        printer.print(": ");
-        n.getStatement().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final EmptyStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final ExpressionStmt n, final Void arg) {
-        printOrphanCommentsBeforeThisChildNode(n);
-        printJavaComment(n.getComment(), arg);
-        n.getExpression().accept(this, arg);
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final SwitchStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("switch(");
-        n.getSelector().accept(this, arg);
-        printer.println(") {");
-        if (n.getEntries() != null) {
-            printer.indent();
-            for (final SwitchEntryStmt e : n.getEntries()) {
-                e.accept(this, arg);
-            }
-            printer.unindent();
-        }
-        printer.print("}");
-    }
-
-    @Override
-    public void visit(final SwitchEntryStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getLabel().isPresent()) {
-            printer.print("case ");
-            n.getLabel().get().accept(this, arg);
-            printer.print(":");
-        } else {
-            printer.print("default:");
-        }
-        printer.println();
-        printer.indent();
-        if (n.getStatements() != null) {
-            for (final Statement s : n.getStatements()) {
-                s.accept(this, arg);
-                printer.println();
-            }
-        }
-        printer.unindent();
-    }
-
-    @Override
-    public void visit(final BreakStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("break");
-        n.getLabel().ifPresent( l -> printer.print(" ").print(l.getIdentifier()));
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final ReturnStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("return");
-        if (n.getExpression().isPresent()) {
-            printer.print(" ");
-            n.getExpression().get().accept(this, arg);
-        }
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final EnumDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        printModifiers(n.getModifiers());
-        printer.print("enum ");
-        n.getName().accept(this, arg);
-        if (!n.getImplementedTypes().isEmpty()) {
-            printer.print(" implements ");
-            for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) {
-                final ClassOrInterfaceType c = i.next();
-                c.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.println(" {");
-        printer.indent();
-        if (n.getEntries() != null) {
-            printer.println();
-            for (final Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext(); ) {
-                final EnumConstantDeclaration e = i.next();
-                e.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        if (!n.getMembers().isEmpty()) {
-            printer.println(";");
-            printMembers(n.getMembers(), arg);
-        } else {
-            if (!n.getEntries().isEmpty()) {
-                printer.println();
-            }
-        }
-        printer.unindent();
-        printer.print("}");
-    }
-
-    @Override
-    public void visit(final EnumConstantDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        n.getName().accept(this, arg);
-        if (!n.getArguments().isEmpty()) {
-            printArguments(n.getArguments(), arg);
-        }
-        if (!n.getClassBody().isEmpty()) {
-            printer.println(" {");
-            printer.indent();
-            printMembers(n.getClassBody(), arg);
-            printer.unindent();
-            printer.println("}");
-        }
-    }
-
-    @Override
-    public void visit(final EmptyMemberDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final InitializerDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.isStatic()) {
-            printer.print("static ");
-        }
-        n.getBody().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final IfStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("if (");
-        n.getCondition().accept(this, arg);
-        final boolean thenBlock = n.getThenStmt() instanceof BlockStmt;
-        if (// block statement should start on the same line
-        thenBlock)
-            printer.print(") ");
-        else {
-            printer.println(")");
-            printer.indent();
-        }
-        n.getThenStmt().accept(this, arg);
-        if (!thenBlock)
-            printer.unindent();
-        if (n.getElseStmt().isPresent()) {
-            if (thenBlock)
-                printer.print(" ");
-            else
-                printer.println();
-            final boolean elseIf = n.getElseStmt().orElse(null) instanceof IfStmt;
-            final boolean elseBlock = n.getElseStmt().orElse(null) instanceof BlockStmt;
-            if (// put chained if and start of block statement on a same level
-            elseIf || elseBlock)
-                printer.print("else ");
-            else {
-                printer.println("else");
-                printer.indent();
-            }
-            if (n.getElseStmt().isPresent())
-                n.getElseStmt().get().accept(this, arg);
-            if (!(elseIf || elseBlock))
-                printer.unindent();
-        }
-    }
-
-    @Override
-    public void visit(final WhileStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("while (");
-        n.getCondition().accept(this, arg);
-        printer.print(") ");
-        n.getBody().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final ContinueStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("continue");
-        n.getLabel().ifPresent( l -> printer.print(" ").print(l.getIdentifier()));
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final DoStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("do ");
-        n.getBody().accept(this, arg);
-        printer.print(" while (");
-        n.getCondition().accept(this, arg);
-        printer.print(");");
-    }
-
-    @Override
-    public void visit(final ForeachStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("for (");
-        n.getVariable().accept(this, arg);
-        printer.print(" : ");
-        n.getIterable().accept(this, arg);
-        printer.print(") ");
-        n.getBody().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final ForStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("for (");
-        if (n.getInitialization() != null) {
-            for (final Iterator<Expression> i = n.getInitialization().iterator(); i.hasNext(); ) {
-                final Expression e = i.next();
-                e.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.print("; ");
-        if (n.getCompare().isPresent()) {
-            n.getCompare().get().accept(this, arg);
-        }
-        printer.print("; ");
-        if (n.getUpdate() != null) {
-            for (final Iterator<Expression> i = n.getUpdate().iterator(); i.hasNext(); ) {
-                final Expression e = i.next();
-                e.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.print(") ");
-        n.getBody().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final ThrowStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("throw ");
-        n.getExpression().accept(this, arg);
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final SynchronizedStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("synchronized (");
-        n.getExpression().accept(this, arg);
-        printer.print(") ");
-        n.getBody().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final TryStmt n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("try ");
-        if (!n.getResources().isEmpty()) {
-            printer.print("(");
-            Iterator<VariableDeclarationExpr> resources = n.getResources().iterator();
-            boolean first = true;
-            while (resources.hasNext()) {
-                visit(resources.next(), arg);
-                if (resources.hasNext()) {
-                    printer.print(";");
-                    printer.println();
-                    if (first) {
-                        printer.indent();
-                    }
-                }
-                first = false;
-            }
-            if (n.getResources().size() > 1) {
-                printer.unindent();
-            }
-            printer.print(") ");
-        }
-        if (n.getTryBlock().isPresent()) {
-            n.getTryBlock().get().accept(this, arg);
-        }
-        for (final CatchClause c : n.getCatchClauses()) {
-            c.accept(this, arg);
-        }
-        if (n.getFinallyBlock().isPresent()) {
-            printer.print(" finally ");
-            n.getFinallyBlock().get().accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final CatchClause n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print(" catch (");
-        n.getParameter().accept(this, arg);
-        printer.print(") ");
-        n.getBody().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final AnnotationDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        printModifiers(n.getModifiers());
-        printer.print("@interface ");
-        n.getName().accept(this, arg);
-        printer.println(" {");
-        printer.indent();
-        if (n.getMembers() != null) {
-            printMembers(n.getMembers(), arg);
-        }
-        printer.unindent();
-        printer.print("}");
-    }
-
-    @Override
-    public void visit(final AnnotationMemberDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printMemberAnnotations(n.getAnnotations(), arg);
-        printModifiers(n.getModifiers());
-        n.getType().accept(this, arg);
-        printer.print(" ");
-        n.getName().accept(this, arg);
-        printer.print("()");
-        if (n.getDefaultValue().isPresent()) {
-            printer.print(" default ");
-            n.getDefaultValue().get().accept(this, arg);
-        }
-        printer.print(";");
-    }
-
-    @Override
-    public void visit(final MarkerAnnotationExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("@");
-        n.getName().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final SingleMemberAnnotationExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("@");
-        n.getName().accept(this, arg);
-        printer.print("(");
-        n.getMemberValue().accept(this, arg);
-        printer.print(")");
-    }
-
-    @Override
-    public void visit(final NormalAnnotationExpr n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("@");
-        n.getName().accept(this, arg);
-        printer.print("(");
-        if (n.getPairs() != null) {
-            for (final Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext(); ) {
-                final MemberValuePair m = i.next();
-                m.accept(this, arg);
-                if (i.hasNext()) {
-                    printer.print(", ");
-                }
-            }
-        }
-        printer.print(")");
-    }
-
-    @Override
-    public void visit(final MemberValuePair n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        n.getName().accept(this, arg);
-        printer.print(" = ");
-        n.getValue().accept(this, arg);
-    }
-
-    @Override
-    public void visit(final LineComment n, final Void arg) {
-        if (!configuration.isPrintComments()) {
-            return;
-        }
-        printer.print("//");
-        String tmp = n.getContent();
-        tmp = tmp.replace('\r', ' ');
-        tmp = tmp.replace('\n', ' ');
-        printer.println(tmp);
-    }
-
-    @Override
-    public void visit(final BlockComment n, final Void arg) {
-        if (!configuration.isPrintComments()) {
-            return;
-        }
-        printer.print("/*").print(n.getContent()).println("*/");
-    }
-
-    @Override
-    public void visit(LambdaExpr n, Void arg) {
-        printJavaComment(n.getComment(), arg);
-        final NodeList<Parameter> parameters = n.getParameters();
-        final boolean printPar = n.isEnclosingParameters();
-        if (printPar) {
-            printer.print("(");
-        }
-        for (Iterator<Parameter> i = parameters.iterator(); i.hasNext(); ) {
-            Parameter p = i.next();
-            p.accept(this, arg);
-            if (i.hasNext()) {
-                printer.print(", ");
-            }
-        }
-        if (printPar) {
-            printer.print(")");
-        }
-        printer.print(" -> ");
-        final Statement body = n.getBody();
-        if (body instanceof ExpressionStmt) {
-            // Print the expression directly
-            ((ExpressionStmt) body).getExpression().accept(this, arg);
-        } else {
-            body.accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(MethodReferenceExpr n, Void arg) {
-        printJavaComment(n.getComment(), arg);
-        Expression scope = n.getScope();
-        String identifier = n.getIdentifier();
-        if (scope != null) {
-            n.getScope().accept(this, arg);
-        }
-        printer.print("::");
-        printTypeArgs(n, arg);
-        if (identifier != null) {
-            printer.print(identifier);
-        }
-    }
-
-    @Override
-    public void visit(TypeExpr n, Void arg) {
-        printJavaComment(n.getComment(), arg);
-        if (n.getType() != null) {
-            n.getType().accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(NodeList n, Void arg) {
-        for (Object node : n) {
-            ((Node) node).accept(this, arg);
-        }
-    }
-
-    @Override
-    public void visit(final ImportDeclaration n, final Void arg) {
-        printJavaComment(n.getComment(), arg);
-        printer.print("import ");
-        if (n.isStatic()) {
-            printer.print("static ");
-        }
-        n.getName().accept(this, arg);
-        if (n.isAsterisk()) {
-            printer.print(".*");
-        }
-        printer.println(";");
-        printOrphanCommentsEnding(n);
-    }
-
-    private void printOrphanCommentsBeforeThisChildNode(final Node node) {
-        if (node instanceof Comment)
-            return;
-        Node parent = node.getParentNode().orElse(null);
-        if (parent == null)
-            return;
-        List<Node> everything = new LinkedList<>();
-        everything.addAll(parent.getChildNodes());
-        sortByBeginPosition(everything);
-        int positionOfTheChild = -1;
-        for (int i = 0; i < everything.size(); i++) {
-            if (everything.get(i) == node)
-                positionOfTheChild = i;
-        }
-        if (positionOfTheChild == -1) {
-            throw new AssertionError("I am not a child of my parent.");
-        }
-        int positionOfPreviousChild = -1;
-        for (int i = positionOfTheChild - 1; i >= 0 && positionOfPreviousChild == -1; i--) {
-            if (!(everything.get(i) instanceof Comment))
-                positionOfPreviousChild = i;
-        }
-        for (int i = positionOfPreviousChild + 1; i < positionOfTheChild; i++) {
-            Node nodeToPrint = everything.get(i);
-            if (!(nodeToPrint instanceof Comment))
-                throw new RuntimeException("Expected comment, instead " + nodeToPrint.getClass() + ". Position of previous child: " + positionOfPreviousChild + ", position of child " + positionOfTheChild);
-            nodeToPrint.accept(this, null);
-        }
-    }
-
-    private void printOrphanCommentsEnding(final Node node) {
-        List<Node> everything = new LinkedList<>();
-        everything.addAll(node.getChildNodes());
-        sortByBeginPosition(everything);
-        if (everything.isEmpty()) {
-            return;
-        }
-        int commentsAtEnd = 0;
-        boolean findingComments = true;
-        while (findingComments && commentsAtEnd < everything.size()) {
-            Node last = everything.get(everything.size() - 1 - commentsAtEnd);
-            findingComments = (last instanceof Comment);
-            if (findingComments) {
-                commentsAtEnd++;
-            }
-        }
-        for (int i = 0; i < commentsAtEnd; i++) {
-            everything.get(everything.size() - commentsAtEnd + i).accept(this, null);
-        }
-    }
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/utils/Bla.java b/javaparser-testing/src/test/resources/com/github/javaparser/utils/Bla.java
deleted file mode 100644
index 21adb88..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/utils/Bla.java
+++ /dev/null
@@ -1,3 +0,0 @@
-class X {
-    
-}
\ No newline at end of file
diff --git a/javaparser-testing/src/test/resources/com/github/javaparser/utils/module-info.java b/javaparser-testing/src/test/resources/com/github/javaparser/utils/module-info.java
deleted file mode 100644
index 2592490..0000000
--- a/javaparser-testing/src/test/resources/com/github/javaparser/utils/module-info.java
+++ /dev/null
@@ -1,2 +0,0 @@
-module M.N {
-}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 3e83d99..36d30a8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,9 +2,11 @@
     <modelVersion>4.0.0</modelVersion>
     <modules>
         <module>javaparser-core</module>
-        <module>javaparser-testing</module>
+        <module>javaparser-core-testing</module>
+        <module>javaparser-core-testing-bdd</module>
         <module>javaparser-core-generators</module>
-        <module>javaparser-metamodel-generator</module>
+        <module>javaparser-core-metamodel-generator</module>
+        <module>javaparser-core-serialization</module>
         <module>javaparser-symbol-solver-model</module>
         <module>javaparser-symbol-solver-logic</module>
         <module>javaparser-symbol-solver-core</module>
@@ -14,12 +16,12 @@
     <groupId>com.github.javaparser</groupId>
     <artifactId>javaparser-parent</artifactId>
     <packaging>pom</packaging>
-    <version>3.5.16-SNAPSHOT</version>
+    <version>3.14.10-SNAPSHOT</version>
 
     <name>javaparser-parent</name>
     <url>https://github.com/javaparser</url>
     <inceptionYear>2007</inceptionYear>
-    <description>Java 9 Parser Parser and Abstract Syntax Tree for Java</description>
+    <description>Java Parser and Abstract Syntax Tree for Java</description>
 
     <licenses>
         <license>
@@ -183,17 +185,17 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-clean-plugin</artifactId>
-                    <version>3.0.0</version>
+                    <version>3.1.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-compiler-plugin</artifactId>
-                    <version>3.7.0</version>
+                    <version>3.8.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-install-plugin</artifactId>
-                    <version>2.5.2</version>
+                    <version>3.0.0-M1</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
@@ -208,27 +210,34 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-resources-plugin</artifactId>
-                    <version>3.0.1</version>
+                    <version>3.1.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-jar-plugin</artifactId>
-                    <version>3.0.2</version>
+                    <version>3.1.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.eluder.coveralls</groupId>
                     <artifactId>coveralls-maven-plugin</artifactId>
                     <version>4.3.0</version>
+                    <dependencies>
+                        <dependency>
+                            <groupId>javax.xml.bind</groupId>
+                            <artifactId>jaxb-api</artifactId>
+                            <version>2.3.1</version>
+                        </dependency>
+                    </dependencies>
                 </plugin>
                 <plugin>
                     <groupId>org.jacoco</groupId>
                     <artifactId>jacoco-maven-plugin</artifactId>
-                    <version>0.7.9</version>
+                    <version>0.8.2</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-javadoc-plugin</artifactId>
-                    <version>3.0.0</version>
+                    <version>3.0.1</version>
                     <configuration>
                         <additionalOptions>
                             <additionalOption>-Xdoclint:none</additionalOption>
@@ -238,7 +247,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-site-plugin</artifactId>
-                    <version>3.7</version>
+                    <version>3.7.1</version>
                     <configuration>
                         <additionalOptions>
                             <additionalOption>-Xdoclint:none</additionalOption>
@@ -248,22 +257,12 @@
                 <plugin>
                     <groupId>biz.aQute.bnd</groupId>
                     <artifactId>bnd-maven-plugin</artifactId>
-                    <version>3.4.0</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-enforcer-plugin</artifactId>
-                    <version>3.0.0-M1</version>
+                    <version>4.1.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <version>2.20.1</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.codehaus.mojo</groupId>
-                    <artifactId>animal-sniffer-maven-plugin</artifactId>
-                    <version>1.16</version>
+                    <version>3.0.0-M1</version>
                 </plugin>
                 <plugin>
                     <groupId>org.codehaus.mojo</groupId>
@@ -273,7 +272,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-deploy-plugin</artifactId>
-                    <version>2.8.2</version>
+                    <version>3.0.0-M1</version>
                 </plugin>
                 <plugin>
                     <groupId>org.codehaus.mojo</groupId>
@@ -288,7 +287,15 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-dependency-plugin</artifactId>
-                    <version>3.0.2</version>
+                    <version>3.1.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>versions-maven-plugin</artifactId>
+                    <version>2.5</version>
+                    <configuration>
+                        <generateBackupPoms>false</generateBackupPoms>
+                    </configuration>
                 </plugin>
             </plugins>
         </pluginManagement>
@@ -298,12 +305,12 @@
             <dependency>
                 <groupId>org.javassist</groupId>
                 <artifactId>javassist</artifactId>
-                <version>3.22.0-GA</version>
+                <version>3.24.0-GA</version>
             </dependency>
             <dependency>
                 <groupId>com.google.guava</groupId>
                 <artifactId>guava</artifactId>
-                <version>23.4-jre</version>
+                <version>27.0-jre</version>
             </dependency>
             <dependency>
                 <groupId>junit</groupId>
@@ -312,15 +319,39 @@
                 <scope>test</scope>
             </dependency>
             <dependency>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-library</artifactId>
+                <version>1.3</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
                 <groupId>org.junit.jupiter</groupId>
-                <artifactId>junit-jupiter-api</artifactId>
-                <version>5.0.0</version>
+                <artifactId>junit-jupiter-engine</artifactId>
+                <version>5.3.1</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.junit.jupiter</groupId>
+                <artifactId>junit-jupiter-params</artifactId>
+                <version>5.3.1</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.junit.vintage</groupId>
+                <artifactId>junit-vintage-engine</artifactId>
+                <version>5.3.1</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.junit-pioneer</groupId>
+                <artifactId>junit-pioneer</artifactId>
+                <version>0.3.0</version>
                 <scope>test</scope>
             </dependency>
             <dependency>
                 <groupId>org.mockito</groupId>
                 <artifactId>mockito-core</artifactId>
-                <version>2.13.0</version>
+                <version>2.23.0</version>
                 <scope>test</scope>
             </dependency>
         </dependencies>
diff --git a/readme.md b/readme.md
index 5596fdf..b584d66 100644
--- a/readme.md
+++ b/readme.md
@@ -1,93 +1,113 @@
-# JavaParser

-

-[![Maven Central](https://img.shields.io/maven-central/v/com.github.javaparser/javaparser-core.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.javaparser%22%20AND%20a%3A%22javaparser-core%22)

-[![Build Status](https://travis-ci.org/javaparser/javaparser.svg?branch=master)](https://travis-ci.org/javaparser/javaparser)

-[![Coverage Status](https://coveralls.io/repos/javaparser/javaparser/badge.svg?branch=master&service=github)](https://coveralls.io/github/javaparser/javaparser?branch=master)

-[![Join the chat at https://gitter.im/javaparser/javaparser](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/javaparser/javaparser?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

-

-This project contains a set of libraries implementing a Java 1.0 - Java 9 Parser with advanced analysis functionalities.

-

-Our main site is at [JavaParser.org](http://javaparser.org)

-

-## Setup

-

-The project binaries are available in Maven Central. 

-

-We strongly advises users to adopt Maven, Gradle or another build system for their projects. If you are not familiar with them

-we suggest taking a look at the maven quickstart projects 

-([javaparser-maven-sample](https://github.com/javaparser/javaparser-maven-sample), 

-[javasymbolsolver-maven-sample](https://github.com/javaparser/javasymbolsolver-maven-sample)).

-

-Just add the following to your maven configuration or tailor to your own dependency management system.

-

-[Please refer to the Migration Guide when upgrading from 2.5.1 to 3.0.0+](https://github.com/javaparser/javaparser/wiki/Migration-Guide)

-

-**Maven**: 

-

-```xml

-<dependency>

-    <groupId>com.github.javaparser</groupId>

-    <artifactId>javaparser-symbol-solver-core</artifactId>

-    <version>3.5.15</version>

-</dependency>

-```

-

-**Gradle**:

-

-```

-compile 'com.github.javaparser:javaparser-symbol-solver-core:3.5.15'

-```

-

-Since Version 3.5.10, the JavaParser project includes the JavaSymbolSolver. 

-While JavaParser generates an Abstract Syntax Tree, JavaSymbolSolver analyzes that AST and is able to find 

-the relation between an element and its declaration (e.g. for a variable name it could be a parameter of a method, providing information about its type, position in the AST, ect).

-

-Using the dependency above will add both JavaParser and JavaSymbolSolver to your project. If you only need the core functionality of parsing Java source code in order to traverse and manipulate the generated AST, you can reduce your projects boilerplate by only including JavaParser to your project:

-

-**Maven**: 

-

-```xml

-<dependency>

-    <groupId>com.github.javaparser</groupId>

-    <artifactId>javaparser-core</artifactId>

-    <version>3.5.15</version>

-</dependency>

-```

-

-**Gradle**:

-

-```

-compile 'com.github.javaparser:javaparser-core:3.5.15'

-```

-

-## How To Compile Sources

-

-If you checked out the project from GitHub you can build the project with maven using:

-

-```

-mvn clean install

-```

-

-If you checkout the sources and want to view the project in an IDE, it is best to first generate some of the source files; otherwise you will get many compilation complaints in the IDE. (mvn clean install already does this for you.)

-

-```

-mvn javacc:javacc

-```

-

-If you modify the code of the AST nodes, specifically if you add or remove fields or node classes,

-the code generators will update a lot of code for you.

-The `run_metamodel_generator.sh` script will rebuild the metamodel,

-which is used by the code generators which are run by `run_core_generators.sh`

-Make sure that `javaparser-core` at least compiles before you run these.

-

-## More information

-

-#### [JavaParser.org](https://www.javaparser.org) is the main information site.

-

-## License

-

-JavaParser is available either under the terms of the LGPL License or the Apache License. You as the user are entitled to choose the terms under which adopt JavaParser.

-

-For details about the LGPL License please refer to [LICENSE.LGPL](ttps://github.com/javaparser/javaparser/blob/master/LICENSE.LGPL).

-

-For details about the Apache License please refer to [LICENSE.APACHE](ttps://github.com/javaparser/javaparser/blob/master/LICENSE.APACHE).

+# JavaParser
+
+[![Maven Central](https://img.shields.io/maven-central/v/com.github.javaparser/javaparser-core.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.javaparser%22%20AND%20a%3A%22javaparser-core%22)
+[![Build Status](https://travis-ci.org/javaparser/javaparser.svg?branch=master)](https://travis-ci.org/javaparser/javaparser)
+[![Coverage Status](https://coveralls.io/repos/javaparser/javaparser/badge.svg?branch=master&service=github)](https://coveralls.io/github/javaparser/javaparser?branch=master)
+[![Join the chat at https://gitter.im/javaparser/javaparser](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/javaparser/javaparser?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![License LGPL-3/Apache-2.0](https://img.shields.io/badge/license-LGPL--3%2FApache--2.0-blue.svg)](LICENSE)
+
+This project contains a set of libraries implementing a Java 1.0 - Java 12 Parser with advanced analysis functionalities.
+
+Our main site is at [JavaParser.org](http://javaparser.org)
+
+## Setup
+
+The project binaries are available in Maven Central. 
+
+We strongly advise users to adopt Maven, Gradle or another build system for their projects.
+If you are not familiar with them we suggest taking a look at the maven quickstart projects 
+([javaparser-maven-sample](https://github.com/javaparser/javaparser-maven-sample), 
+[javasymbolsolver-maven-sample](https://github.com/javaparser/javasymbolsolver-maven-sample)).
+
+Just add the following to your maven configuration or tailor to your own dependency management system.
+
+[Please refer to the Migration Guide when upgrading from 2.5.1 to 3.0.0+](https://github.com/javaparser/javaparser/wiki/Migration-Guide)
+
+**Maven**: 
+
+```xml
+<dependency>
+    <groupId>com.github.javaparser</groupId>
+    <artifactId>javaparser-symbol-solver-core</artifactId>
+    <version>3.14.9</version>
+</dependency>
+```
+
+**Gradle**:
+
+```
+implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.14.9'
+```
+
+Since Version 3.5.10, the JavaParser project includes the JavaSymbolSolver. 
+While JavaParser generates an Abstract Syntax Tree, JavaSymbolSolver analyzes that AST and is able to find 
+the relation between an element and its declaration (e.g. for a variable name it could be a parameter of a method, providing information about its type, position in the AST, ect).
+
+Using the dependency above will add both JavaParser and JavaSymbolSolver to your project. If you only need the core functionality of parsing Java source code in order to traverse and manipulate the generated AST, you can reduce your projects boilerplate by only including JavaParser to your project:
+
+**Maven**: 
+
+```xml
+<dependency>
+    <groupId>com.github.javaparser</groupId>
+    <artifactId>javaparser-core</artifactId>
+    <version>3.14.9</version>
+</dependency>
+```
+
+**Gradle**:
+
+```
+implementation 'com.github.javaparser:javaparser-core:3.14.9'
+```
+
+Since version 3.6.17 the AST can be serialized to JSON.
+There is a separate module for this:
+
+**Maven**: 
+
+```xml
+<dependency>
+    <groupId>com.github.javaparser</groupId>
+    <artifactId>javaparser-core-serialization</artifactId>
+    <version>3.14.9</version>
+</dependency>
+```
+
+**Gradle**:
+
+```
+implementation 'com.github.javaparser:javaparser-core-serialization:3.14.9'
+```
+
+## How To Compile Sources
+
+If you checked out the project from GitHub you can build the project with maven using:
+
+```
+mvn clean install
+```
+
+If you checkout the sources and want to view the project in an IDE, it is best to first generate some of the source files; otherwise you will get many compilation complaints in the IDE. (mvn clean install already does this for you.)
+
+```
+mvn javacc:javacc
+```
+
+If you modify the code of the AST nodes, specifically if you add or remove fields or node classes,
+the code generators will update a lot of code for you.
+The `run_metamodel_generator.sh` script will rebuild the metamodel,
+which is used by the code generators which are run by `run_core_generators.sh`
+Make sure that `javaparser-core` at least compiles before you run these.
+
+## More information
+
+#### [JavaParser.org](https://javaparser.org) is the main information site.
+
+## License
+
+JavaParser is available either under the terms of the LGPL License or the Apache License. You as the user are entitled to choose the terms under which adopt JavaParser.
+
+For details about the LGPL License please refer to [LICENSE.LGPL](ttps://github.com/javaparser/javaparser/blob/master/LICENSE.LGPL).
+
+For details about the Apache License please refer to [LICENSE.APACHE](ttps://github.com/javaparser/javaparser/blob/master/LICENSE.APACHE).
diff --git a/ruleset.xml b/ruleset.xml
new file mode 100644
index 0000000..371fbe1
--- /dev/null
+++ b/ruleset.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ruleset  name="Default Maven PMD Plugin Ruleset">
+  <description>
+The default ruleset used by the Maven PMD Plugin, when no other ruleset is specified. It contains the rules of the old (pre PMD 6.0.0) rulesets java-basic, java-empty, java-imports, java-unnecessary, java-unusedcode. This ruleset might be used as a starting point for an own customized ruleset [0]. [0] https://pmd.github.io/latest/pmd_userdocs_understanding_rulesets.html
+</description>
+    <rule ref="rulesets/java/imports.xml/DontImportJavaLang">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/strings.xml/StringToString">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/BigIntegerInstantiation">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/migrating.xml/IntegerInstantiation">
+       <priority>3</priority>
+   </rule>
+   <rule ref="rulesets/java/imports.xml/DuplicateImports">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/SimplifyBooleanExpressions">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/finalizers.xml/EmptyFinalizer">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/migrating.xml/ByteInstantiation">
+       <priority>3</priority>
+   </rule>
+   <rule ref="rulesets/java/imports.xml/TooManyStaticImports">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/AvoidUsingOctalValues">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/EqualsNull">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/ClassCastExceptionWithToArray">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/AvoidMultipleUnaryOperators">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/naming.xml/AvoidDollarSigns">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/ClassWithOnlyPrivateConstructorsShouldBeFinal">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/BooleanInstantiation">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/naming.xml/NoPackage">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/CompareObjectsWithEquals">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/finalizers.xml/FinalizeOnlyCallsSuperFinalize">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/JumbledIncrementer">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/PositionLiteralsFirstInComparisons">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/strings.xml/UseStringBufferLength">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/controversial.xml/DontImportSun">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/finalizers.xml/FinalizeOverloaded">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/AvoidProtectedFieldInFinalClass">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/ReturnFromFinallyBlock">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/strings.xml/UnnecessaryCaseChange">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/finalizers.xml/FinalizeShouldBeProtected">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/controversial.xml/SuspiciousOctalEscape">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/AvoidThreadGroup">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/naming.xml/ClassNamingConventions">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/controversial.xml/AvoidUsingNativeCode">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/finalizers.xml/FinalizeDoesNotCallSuperFinalize">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/migrating.xml/ShortInstantiation">
+       <priority>3</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/UnconditionalIfStatement">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/AvoidDecimalLiteralsInBigDecimalConstructor">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/MisplacedNullCheck">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/naming.xml/SuspiciousEqualsMethodName">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/IdempotentOperations">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/migrating.xml/LongInstantiation">
+       <priority>3</priority>
+   </rule>
+   <rule ref="rulesets/java/imports.xml/ImportFromSamePackage">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/SimplifyConditional">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/finalizers.xml/AvoidCallingFinalize">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/design.xml/UseCollectionIsEmpty">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/naming.xml/SuspiciousHashcodeMethodName">
+       <priority>2</priority>
+   </rule>
+   <rule ref="rulesets/java/basic.xml/BrokenNullCheck">
+       <priority>2</priority>
+   </rule>
+</ruleset>
diff --git a/run_core_generators.sh b/run_core_generators.sh
index 3fb9241..931d8ae 100755
--- a/run_core_generators.sh
+++ b/run_core_generators.sh
@@ -7,13 +7,13 @@
 pushd javaparser-core-generators
 
 # Generate code
-mvn clean package -P run-core-generators -DskipTests
+mvn -B clean package -P run-generators -DskipTests
 
 # Go back to previous directory
 popd
 
 # Fresh code has been generated in core, so rebuild the whole thing again.
-mvn clean install -DskipTests
+mvn -B clean install -DskipTests
 if [ "$?" -ne 0 ]; then
     exit 1
 fi
diff --git a/run_core_metamodel_generator.sh b/run_core_metamodel_generator.sh
new file mode 100755
index 0000000..4a55c67
--- /dev/null
+++ b/run_core_metamodel_generator.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# Rebuilds the metamodel based on the nodes in javaparser-core
+
+# We introspect the nodes in javaparser-core, so we need an update build of it. 
+mvn -B clean install -DskipTests
+if [ "$?" -ne 0 ]; then
+    exit 1
+fi
+
+# Remember current directory
+pushd javaparser-core-metamodel-generator
+
+# Generate code
+mvn -B clean package -P run-generators -DskipTests
+
+# Go back to previous directory
+popd
+
+# Fresh code has been generated in core, so rebuild the whole thing again.
+mvn -B clean install -DskipTests
+if [ "$?" -ne 0 ]; then
+    exit 1
+fi
diff --git a/run_metamodel_generator.sh b/run_metamodel_generator.sh
deleted file mode 100755
index 2644f98..0000000
--- a/run_metamodel_generator.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-
-# Rebuilds the metamodel based on the nodes in javaparser-core
-
-# We introspect the nodes in javaparser-core, so we need an update build of it. 
-mvn clean install -DskipTests
-if [ "$?" -ne 0 ]; then
-    exit 1
-fi
-
-# Remember current directory
-pushd javaparser-metamodel-generator
-
-# Generate code
-mvn clean package -P run-metamodel-generator -DskipTests
-
-# Go back to previous directory
-popd
-
-# Fresh code has been generated in core, so rebuild the whole thing again.
-mvn clean install -DskipTests
-if [ "$?" -ne 0 ]; then
-    exit 1
-fi